how to consume json web service in worklight - ibm-mobilefirst

xml file (HofDetails.xml) for adapter is:
<protocol>http</protocol>
<domain>172.16.32.44</domain>
<port>8080</port>
my adapter code is :
file : HofDetails-impl.js
function getHofDetails(){
path = "/jsonWebService/rest/UserInfoService/module";
var input = {
method : 'get',
returnedContentType:'plain/json',
path : path,
parameters : {
'Eid' : '0',
'bhamashahid' : '0',
'aadhar_id' : '0',
'mobileNo' : '1'
}
};
return WL.Server.invokeHttp(input);
//return {result : "12345"};
}
and defination of my web service looks like this :
#GET
#Path("/module/{Eid}/{bhamashahid}/{aadhar_id}/{mobileNo}")
#Produces(MediaType.APPLICATION_JSON)
public String getAll(#PathParam("Eid") String eid,#PathParam("bhamashahid") String bhamashahid,#PathParam("aadhar_id") String aadhar,#PathParam("mobileNo") String mobileNo) {
// return JsonObject.toJsonString();
}

You have not actually explained what is the issue you are having.
What is the issue?
Also, it appears that you are not actually processing the response.
How about something like this:
var response = WL.Server.invokeHttp(input);
response.someProperty = "something";
return response;

Related

Update appsetting.json in run time in .netcore

I have this appsetting json file :
"RavenOptions": {
"PublicUrl": "http://127.0.0.1:61570",
"PublicDbName": "TestHostBuilder_ctor_1",
"TseDbName": "TestHostBuilder_ctor_1",
"IsHttps": "false",
"CertificateDirectory": "",
"ShardUrls": [
"http://127.0.0.1:61570",
"http://127.0.0.1:61570",
"http://127.0.0.1:61570",
"http://127.0.0.1:61570"
]
}
I need to update the values of the file in runtime .I am using this function :
public static void AddOrUpdateAppSetting<T>(string key, T value)
{
try
{
var filePath = Path.Combine(AppContext.BaseDirectory, "appSettingTest.json");
string json = File.ReadAllText(filePath);
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
var sectionPath = key.Split(":")[0];
if (!string.IsNullOrEmpty(sectionPath))
{
var keyPath = key.Split(":")[1];
jsonObj[sectionPath][keyPath] = value;
}
else
{
jsonObj[sectionPath] = value; // if no sectionpath just set the value
}
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(filePath, output);
}
catch (ConfigurationErrorsException)
{
Console.WriteLine("Error writing app settings");
}
}
this function works fine but the problem is when I want to update the values of sharedurls (this is an array) the result is like this :
All records are in one row .But I need tho be like this :
every records is one row.
Here is my update code :
string serverAddress = "\""+documentStore.Identifier.Split("(").First()+"\"";
Appset.AddOrUpdateAppSetting("RavenOptions:PublicDbName", documentStore.Database);
Appset.AddOrUpdateAppSetting("RavenOptions:PublicUrl", documentStore.Identifier.Split("(").First());
Appset.AddOrUpdateAppSetting("RavenOptions:ShardUrls","["+String.Join(",", Enumerable.Repeat(serverAddress, 4).ToArray())+"]");

What is the best possible way to send custom error responses in .net core web api

I'm making a .net Core WebApi using .Net Core 2.2. The API is ready but the failure message and response is where I'm stuck at.
Right now, I'm getting respose like below
json
{
"empId":1999,
"empName":"Conroy, Deborah",
"enrollmentStatus":true,
"primaryFingerprintScore":65,
"secondaryFingerprintScore":60,
"primaryFingerprint":null,
"secondaryFingerprint":null,
"primaryFingerprintType":null,
"secondaryFingerprintType":null}
}
I created a json formatter class and wrote the below code
public class SuperJsonOutputFormatter : JsonOutputFormatter
{
public SuperJsonOutputFormatter(
JsonSerializerSettings serializerSettings,
ArrayPool<char> charPool) : base(serializerSettings, charPool)
{
}
public override async Task WriteResponseBodyAsync(
OutputFormatterWriteContext context,
Encoding selectedEncoding)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
if (selectedEncoding == null)
throw new ArgumentNullException(nameof(selectedEncoding));
using (TextWriter writer =
context.WriterFactory(
context.HttpContext.Response.Body,
selectedEncoding))
{
var rewrittenValue = new
{
resultCode = context.HttpContext.Response.StatusCode,
resultMessage =
((HttpStatusCode)context.HttpContext.Response.StatusCode)
.ToString(),
result = context.Object
};
this.WriteObject(writer, rewrittenValue);
await writer.FlushAsync();
}
}
I expect all the error codes to be sent as generic error messages like the JSON below.
FOR STATUS OKAY:
{
"status" : True,
"error" : null,
"data" : {
{
"empId":1999,
"empName":"Conroy, Deborah",
"enrollmentStatus":true,
"primaryFingerprintScore":65,
"secondaryFingerprintScore":60,
"primaryFingerprint":null,
"secondaryFingerprint":null,
"primaryFingerprintType":null,
"secondaryFingerprintType":null}
}
}
}
FOR OTHER STATUS LIKE 404, 500, 400, 204
{
"status" : False,
"error" : {
"error code" : 404,
"error description" : Not Found
},
"data" : null
}
I expect all the error codes to be sent as generic error messages like the JSON below
You're almost there. What you need to do is enabling your SuperJsonOutputFormatter.
A Little Change to Your Formatter
Firstly, your formatter didn't return a json with the same schema as you want. So I create a dummy class to hold the information for error code and error description:
public class ErrorDescription{
public ErrorDescription(HttpStatusCode statusCode)
{
this.Code = (int)statusCode;
this.Description = statusCode.ToString();
}
[JsonProperty("error code")]
public int Code {get;set;}
[JsonProperty("error description")]
public string Description {get;set;}
}
And change your WriteResponseBodyAsync() method as below:
...
using (TextWriter writer = context.WriterFactory(context.HttpContext.Response.Body, selectedEncoding)) {
var statusCode = context.HttpContext.Response.StatusCode;
var rewrittenValue = new {
status = IsSucceeded(statusCode),
error = IsSucceeded(statusCode) ? null : new ErrorDescription((HttpStatusCode)statusCode),
data = context.Object,
};
this.WriteObject(writer, rewrittenValue);
await writer.FlushAsync();
}
Here the IsSucceeded(statusCode) is a simple helper method that you can custom as you need:
private bool IsSucceeded(int statusCode){
// I don't think 204 indicates that's an error.
// However, you could comment out it if you like
if(statusCode >= 400 /* || statusCode==204 */ ) { return false; }
return true;
}
Enable your Formatter
Secondly, to enable your custom Formatter, you have two approaches: One way is to register it as an global Formatter, the other way is to enable it for particular Controller or Action. Personally, I believe the 2nd way is better. So I create a Action Filter to enable your formatter.
Here's an implementation of the Filter that enables your custom formatter dynamically:
public class SuperJsonOutputFormatterFilter : IAsyncActionFilter{
private readonly SuperJsonOutputFormatter _formatter;
// inject your SuperJsonOutputFormatter service
public SuperJsonOutputFormatterFilter(SuperJsonOutputFormatter formatter){
this._formatter = formatter;
}
// a helper method that provides an ObjectResult wrapper over the raw object
private ObjectResult WrapObjectResult(ActionExecutedContext context, object obj){
var wrapper = new ObjectResult(obj);
wrapper.Formatters.Add(this._formatter);
context.Result= wrapper;
return wrapper;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
ActionExecutedContext resultContext = await next();
// in case we get a 500
if(resultContext.Exception != null && ! resultContext.ExceptionHandled){
var ewrapper = this.WrapObjectResult(resultContext, new {});
ewrapper.StatusCode = (int) HttpStatusCode.InternalServerError;
resultContext.ExceptionHandled = true;
return;
}
else {
switch(resultContext.Result){
case BadRequestObjectResult b : // 400 with an object
var bwrapper=this.WrapObjectResult(resultContext,b.Value);
bwrapper.StatusCode = b.StatusCode;
break;
case NotFoundObjectResult n : // 404 with an object
var nwrapper=this.WrapObjectResult(resultContext,n.Value);
nwrapper.StatusCode = n.StatusCode;
break;
case ObjectResult o : // plain object
this.WrapObjectResult(resultContext,o.Value);
break;
case JsonResult j : // plain json
this.WrapObjectResult(resultContext,j.Value);
break;
case StatusCodeResult s: // other statusCodeResult(including NotFound,NoContent,...), you might want to custom this case
var swrapper = this.WrapObjectResult(resultContext, new {});
swrapper.StatusCode = s.StatusCode;
break;
}
}
}
}
And don't forget to register your formatter as a service :
services.AddScoped<SuperJsonOutputFormatter>();
Finally, when you want to enable your formatter, just add a [TypeFilter(typeof(SuperJsonOutputFormatterFilter))] annotation for the controller or action.
Demo
Let's create an action method for Test:
[TypeFilter(typeof(SuperJsonOutputFormatterFilter))]
public IActionResult Test(int status)
{
// test json result(200)
if(status == 200){ return Json(new { Id = 1, }); }
// test 400 object result
else if(status == 400){ return BadRequest( new {}); }
// test 404 object result
else if(status == 404){ return NotFound(new { Id = 1, }); }
// test exception
else if(status == 500){ throw new Exception("unexpected exception"); }
// test status code result
else if(status == 204){ return new StatusCodeResult(204); }
// test normal object result(200)
var raw = new ObjectResult(new XModel{
empId=1999,
empName = "Conroy, Deborah",
enrollmentStatus=true,
primaryFingerprintScore=65,
secondaryFingerprintScore=60,
primaryFingerprint = null,
secondaryFingerprint= null,
primaryFingerprintType=null,
secondaryFingerprintType=null
});
return raw;
}
Screenshot:

JAX-RS : HTTP Status 415 - Unsupported Media Type

I got this error when making an ajax request to my WebService :
HTTP Status 415 - Unsupported Media Type
I tried to add the good MediaType (Text/Html, i think), but it doesn't work. I have still this error. What could this be, do you think ?
Thank you !
My request :
$(document).on('submit','.form-add-edit',function(e){
e.preventDefault();
var idDisruptive = $(e.target).find('input[name=idDisruptive]').val();
var url = "api/disruptive";
var method = "POST";
if (idDisruptive){
url = url + '/' + idDisruptive;
method = "PUT";
}
$.ajax({
url: url,
method : method,
data : getDisruptiveParams(),
success : function (response){
console.log('EDIT')
console.log(response);
//editDisruptive(response);
},
error : function(response){
console.log('EDIT ERROR')
console.log(response);
}
});
});
The Web Service :
#Stateless
#Path("disruptive")
#Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_HTML, MediaType.APPLICATION_XML, MediaType.APPLICATION_FORM_URLENCODED})
#Produces({MediaType.APPLICATION_JSON})
public class DisruptiveFacadeREST extends AbstractFacade<Disruptive> {
#PersistenceContext(unitName = "StoryGeneratorPU")
private EntityManager em;
public DisruptiveFacadeREST() {
super(Disruptive.class);
}
#POST
#Override
public void create(Disruptive entity) {
super.create(entity);
}
#PUT
#Path("{id}")
public void edit(#PathParam("id") Integer id, Disruptive entity) {
super.edit(entity);
}
#Override
protected EntityManager getEntityManager() {
return em;
}
}
You need to set the content-type on the jQuery request. If you don't, it will default to application/x-www-form-urlencoded. And just because you add #Consumes(MediaType.APPLICATION_FORM_URLENCODED) doesn't mean that JAX-RS will not how to convert the form data to Disruptive. There need to be a MessageBodyReader to handle that conversion, which there isn't. Same goes for MediaType.TEXT_HTML. Just adding that means nothing if there is no converter to handle the conversion. Remove those two. What you want is to handle JSON conversion, and there should already be a MessageBodyReader included in the EE server that will convert JSON data to arbitrary POJOs.
So for the jQuery, just add
$.ajax({
contentType: 'application/json'
})
That should solve the problem.

How to request same parameter twice in query string?

I am trying to request the following query string url: api/item?name=storm&name=prest
I am using the following code below and I cannot get the code to work.
public class ItemController : ApiController
{
private cdwEntities db = new cdwEntities();
public HttpResponseMessage Get([FromUri] Query query)
{
var data = db.database_ICs.AsQueryable();
if (query.name != null)
{
**data = data.Where(c => c.Name.Split("&").Contains(query.name));**
}
if (query.id!= null)
{
data = data.Where(c => c.ID== query.id);
}
if (!data.Any())
{
var message = string.Format("No data was found");
return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
}
return Request.CreateResponse(HttpStatusCode.OK, data);
}
}
Any help would be very much appreciated.
You can use post Api and send array of [name].
name = [item1,item2....]
public void Post([FromBody] List<string> name) {
}
You can not pass same name key in Querystring. Browser/Code did not identified which is correct value, if you want multiple value then pass as a object.

How to validate file upload? [Play Framework]

I have a simple bean, like that:
package models;
import play.data.validation.Constraints;
public class Upload
{
#Constraints.Required
#Constraints.MinLength(4)
#Constraints.MaxLength(40)
public String name;
#Constraints.Required
public String inputFile;
}
and form, like that:
#form(action = routes.Application.submit(), 'enctype -> "multipart/form-data") {
#inputText(
uploadForm("name"),
'_label -> "Name"
)
#inputFile(
uploadForm("inputFile"),
'_label -> "Queries"
)
}
What is the best way to validate inputFile?
Is it possible do to that with annotations?
#Required constraint does not work at all.
I want it to be selected + add some limitation on size.
make your form like:
<input type="file" name="inputFile">
In you submit method add this:
// from official documentation
public static Result submit() {
MultipartFormData body = request().body().asMultipartFormData();
FilePart file = body.getFile("inputFile");
if (inputFile != null) {
String fileName = picture.getFilename();
String contentType = picture.getContentType();
File file = picture.getFile();
// method the check size
if(!validateFileSize){
return redirect(routes.Application.index()); // error in file size
}
return ok("File uploaded");
} else {
// here comes the validation
flash("error", "Missing file");
return redirect(routes.Application.index());
}
}
Something like the following, maybe?
MultipartFormData body = request().body().asMultipartFormData();
if (!body.getFiles().isEmpty()) {
// do your work
}