Parse JSON request without creating a class - spring

In a Spring MVC controller method, I have a JSON input (request body) with just one field: {"version":3}. I can get this value like this:
#RequestMapping
public void myMethod(#RequestBody MyJsonRequest myJsonRequest) {
int version = myJsonRequest.version;
//...
}
But I have to create MyJsonRequest class with a version field. How can I get the version value without creating a new class?

You can try using a map:
public void myMethod(#RequestBody Map<String, Integer> myJsonRequest) {
int version = myJsonRequest.get("version");
//...
}

You can parse JSON data and then you can directly access to value of JSON response.
Consider data as myJsonRequest :
var version=0;
var jsonval = $.parseJSON(data);
// you can use directly value of json data like
version = data.version;
// If you returned an array in json response, then you can use $.each method and store value into single array, like this
$.each(portals_array,function(i,v){
version[] = v.version;
});
alert(version);
};
It's working perfectly in my code. Check it out.

Try the code below, it maps your json object to a primitive int variable:
#RequestMapping(value="/yourMapping", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON)
public void myMethod (#RequestBody int version) {
//do something with your int variable version
}

Related

Post Binary array to Web API Controller

I am trying to POST form data which consists of few string variable and binary array.
Below is the Model for the form data.
public class FileModel
{
public string Path { get; set; }
public byte[] File { get; set; }
}
Below is my Web API Controller.
[Route("")]
public IHttpActionResult Post([FromBody]FileModel media)
{
// Can I use ??
byte[] requestFile = media.File;
string requestFilePath = media.Path;
//Process the above variables
return Ok();
}
I would like to know Can I use the following code to de-serialize the following code snippet to to read the values from the JSON payload including the binary data?
byte[] requestFile = media.File;
string requestFilePath = media.Path;
If Yes, Do I need to define any formatter class to get it working?
I normally use POSTMAN to test my RESTful endpoints.
Is it possible to use POSTMAN still to POST binary array? May be not need to write my own client
You'll need to use a serializer to serialize complex objects (multiple fields) as content for a Http Request.
For your code snippet to read the object from the content you can use this:
var requestContent = Request.Content.ReadAsAsync<FileModel>(GetJsonSerializer()).Result;
Here's the serializer boilerplate code.
private JsonMediaTypeFormatter GetJsonSerializer()
{
JsonSerializerSettings settings = new JsonSerializerSettings()
{
PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All,
TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All
};
return new JsonMediaTypeFormatter() { SerializerSettings = settings };
}
I'm not sure how to use POSTMAN to test this. A simple .net client would be:
var Client = new HttpClient();
Client.BaseAddress = new Uri("localhost"); //whatever your endpoint is
FileModel objectToSend = new FileModel();
var objectContent = new ObjectContent<FileModel>(objectToSend, GetJsonSerializer() );
var response = Client.PostAsync("uri", objectContent);
You are able to use POSTMAN to test binary file input. Selecting the body tab, you can then pick the radio button "binary" and then choose file.

Referencing Action Parameters from ExceptionLogger

I'm wanting to make use of the new method for globally logging errors. I've written a class that inherits ExceptionLogger and overrides the Log() method. Then registered it as a replacement.
public class TraceExceptionLogger : ExceptionLogger
{
public async override void Log(ExceptionLoggerContext context)
{
// This is always empty string
var content = await context.Request.Content.ReadAsStringAsync();
// This is almost always null
var actionContext = context.ExceptionContext.ActionContext;
}
}
I can dig through the ExceptionLoggerContext object's properties to get pretty much everything I need, EXCEPT for action parameters. There is indeed an ActionContext property but I've only seen it null and this wiki page states that ActionContext and ControllerContext will almost always be null.
Also, I can't get the content stream because its stream is already read before it gets to my logger. So there's no way for me to get any posted json from the request's content.
Is there maybe a way to get the posted data from HttpContext.Current or in some other way?
Ok it looks like I can get the body text from HttpContext by reading InputStream on the Request object like this:
string bodyText = string.Empty;
using (var sr = new StreamReader(HttpContext.Current.Request.InputStream))
{
sr.BaseStream.Seek(0, SeekOrigin.Begin);
bodyText = sr.ReadToEnd();
}
This code has been successful me so far for getting my posted json data.
Here's action parameters for future reference
public class HomeController : ApiController {
public string Get(string id, [FromHeader] Whoever whoever) {
public string Post(Whatever whatever) {
var args = ((ApiController) context.ExceptionContext
.ControllerContext.Controller)).ActionContext.ActionArguments
if (args.ContainsKey("whatever")) {
var whatever = (Whatever)args["whatever"];

ASP.New Web API - Model Binding and Inheritance?

Is it possible for a Controller method to handle all Posted items which derive from a particular base class? The idea is to be able to dispatch Commands by posting them to an endpoint. When I try the following, the "cmd" parameter in the Post method is always null.
Example
//the model:
public abstract class Command{
public int CommandId{get; set;}
}
public class CommandA:Command{
public string StringParam{get; set;}
}
public class CommandB:Command{
public DateTime DateParam{get; set;}
}
//and in the controller:
public HttpResponseMessage Post([FromBody]Command cmd)
{
//cmd parameter is always null when I Post a CommandA or CommandB
//it works if I have separate Post methods for each Command type
if (ModelState.IsValid)
{
if (cmd is CommandA)
{
var cmdA = (CommandA)cmd;
// do whatever
}
if (cmd is CommandB)
{
var cmdB = (CommandB)cmd;
//do whatever
}
//placeholder return stuff
var response = Request.CreateResponse(HttpStatusCode.Created);
var relativePath = "/api/ToDo/" + cmd.TestId.ToString();
response.Headers.Location = new Uri(Request.RequestUri, relativePath);
return response;
}
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
Again, when I try this approach the Post method gets called, but the parameter is always null from the framework. However if I replace it with a Post method with a specific CommandA parameter type, it works.
Is what I'm attempting possible? Or does every message type need a separate handler method in the controller?
If you are sending data in Json format, then following blog gives more details about how hierarchies deserialization can be achieved in json.net:
http://dotnetbyexample.blogspot.com/2012/02/json-deserialization-with-jsonnet-class.html

How to compose and post a JSON object from jQuery to an MVC3 action method?

I have the following JavaScript code that gets the Id property (Guid) from every user row in a Kendo UI grid. Now I am wondering how best to compose these Id's and the owner roleId into a JSON object that I can pass to an MVC3 action method. Versus my silly string concat.
$("#command-add-selected").click(function () {
var json = "roleId: '51FC554E-353C-4D55-BE52-1B4BF9D2F17F', users: [";
var avail = $("#availableUsersGrid").data().kendoGrid._data;
for (var i = 0; i < avail.length; i++) {
json += "{ Id: '" + avail[i].Id + "'},";
}
json = json.slice(0, -1);
json += "]";
alert(json);
return false;
});
The action method can be GET or POST and need not return any value (this is another puzzle here, no returned view). All it does is domain updates that are fetched by other ajax code subsequent to the above code.
How can I pass the above type JSON to an action method essentially of void return type?
EDIT: This question answered the minor part of my question nicely, with how to dynamically add items to an array with push.
1.first of all u dont need to create the full json ur self use JSON.Stringify() method to change the javascript object to JSON string.
2.after u have created the JSON string u can GET or POST it to any normal method in any MVC Controller of visibility public.
even if the signature of the action method is like public ActionResult MehodName(string jsonString) u can always return null.
3. u can use built in JavaScriptSerializer class in System.Web.Script.Serialization namespace to deserialize the json string u recieve in the action to create an object with the same propertiese
Edit:-
make a javascript array names users then inside the for loop use .push() function of javascript to insert the objects like this
var users = [];
for(something)
{
var user = {"Id":"YOUR ID VALUE"};
users.push(user)
}
var objectToSerialize = {"roleId":"YOUR ROLE GUID","Users":users};
var jsonString = JSON.stringify(objectToSerialize);
Edit 2:-
so going by your previous comments u dont want that u need to deseralize the whole JSON object. going by your object architecture even if ur action method has a signature like this
public ActionResult GetUsersByRole(Users users)
{
//some code
}
and Users class like this one
class Users
{
public string RoleId{get; set;}
public User[]{get; set;}
}
and User class like this
class User
{
string Id{get; set;}
}
it would automatically bind property with your complex users object
In conjunction with Parv Sharma's solution:
function User(id) { this.Id=id; }
$("#command-add-selected").click(function () {
var avail = $("#availableUsersGrid").data().kendoGrid._data;
var userArray = array();
for (var i = 0; i < avail.length; i++) {
userArray.push(new User(avail[i].Id));
}
var obj = {roleId:'51FC554E-353C-4D55-BE52-1B4BF9D2F17F',users:userArray};
alert(JSON.stringify(obj));
return false;
});
Should just be able to use Url.Action("NameofAction","nameofcontroller", json);
You may have to add an AcceptVerbs attribute to the action method as well, depending on if you want it to be a GET or a POST.
As far as the building part goes, I would suggest not using strings at all. Jsons are objects, not strings, so I would go ahead and build a "users" object with your foreach loop and then throw that object into your json return object.
edit: forgot to mention stringify. Yeah. Use that.

ASP.NET MVC 3 Parse JSon object and display data

I have a class
public class ConversionResultModel
{
public string ProcessId { get; set; }
public bool Result { get; set; }
public string Message { get; set; }
}
sending it to view using JSon
public ActionResult UploadFile(IEnumerable<HttpPostedFileBase> clientUpload)
{
string destinationPath = "";
JsonResult result = null;
var fileModel = new ConversionResultModel();
fileModel.ProcessId = "4558-95559-554";
fileModel.Result = true;
fileModel.Message = "test.pdf";
result = Json(new { fileModel }, "text/plain");
return result;
}
How to parse such JSon object at client side using JS or jQuery and read values?
I have tried to parse JSon object with code below but get Undefined error in alert
var obj = $.parseJSON(e.response);
alert(e.obj);
I receive JSon object like this
{"fileModel":{"ProcessId":"4558-95559-554","Result":true,"Message":null,"SourceFile":null,"ConvertedFileName":"test.pdf","ConvertedFileSize":1233444,"DownloadUrl":"http://localhost:2008/download?path=4558-95559-554","DeleteUrl":"http://localhost:2008/download?path=4558-95559-554"}}
You do not need to parse it. Just set data type to JSON during ajax request and then use received data object like entity and you easily can access to any property:
var id = data.ProcessId;
Anyway, using jQuery you can parse JSON string:
var data = jQuery.parseJSON(stringData);
P.S:
Use the following code sample for converting object to JSON in ASP.NET MVC:
return this.Json(fileModel);
http://api.jquery.com/jQuery.parseJSON/
In your case, I think you're getting back the correct JSON, but your alert is looking at the wrong object. Try alert(obj.SomeProperty) rather than alert(e.obj). e.obj doesn't exist, which is likely why you're getting an "undefined" error. For example, alert(obj.fileModel.ProcessId); should work.

Resources