1

From chrome developer tools I see that my request is sending this info to my controller:

models:[{"Id":null,"Start":"2014-06-11T12:17:52.452Z","End":"2014-06-11T12:17:52.452Z","Name":"test","Status":"test"}]

How can I accept it in my MVC controller?

It looks like to be a javascript array with one element.

On serverside I have method accepting : Foo(Bar models) and also tried Foo(List<Bar> models)

The models value is always null. Any suggestions, how to get the value to my server?

5
  • It would be better if you post the code that send this string to the controller instead. Commented Jun 11, 2014 at 12:36
  • How is this being passed (AJAX?) You may need to specify the dataType parameter so MVC knows it's JSON incoming and not just a string value. Commented Jun 11, 2014 at 13:00
  • @BradChristie I have dataType: "json" and its weird, when I change my controller to accept Foo(object models) the object is a list that contains a string "[{\"Id\":null,\"StartDate\":\"2014-06-11T13:08:19.483Z\",\"EndDate\":\"2014-06-11T13:08:19.483Z\",\"Name\":\"test\",\"Status\":\"test\"}]", it seems like ModelBinding is broken or something, since when I put real model, I get null. Commented Jun 11, 2014 at 13:09
  • @Jaanus: Give me a few moments, putting together working example for you. (And I assume this is AJAX, correct?) Commented Jun 11, 2014 at 13:11
  • This is ajax, yes. btw if it gives more info, using kendo grid inline item creation. demos.telerik.com/kendo-ui/grid/editing-inline , this is the request from chrome dev tools. maybe something wrong with headers pastebin.com/Yj1sckq0 Commented Jun 11, 2014 at 13:17

4 Answers 4

2

So to pass the information using AJAX, you need to supply two parameters: dataType and contentType. (I suppose dataType is optional, but if you're expecting JSON back it's better to supply it.). The contentType, however, lets MVC [the ModelBinder] know the incoming request isn't just a string, but that it's an object that needs to be deserialized back into objects.

with that said, something like the following should work for your circumstance:

// This is your to-be-sent data'
// However you collect it, but for now we're storing it as a plain object.
var jso = { models: [{ "Id": null, "Start": "2014-06-11T12:17:52.452Z", "End": "2014-06-11T12:17:52.452Z", "Name": "test", "Status": "test" }] }

// Here we turn it into JSON
var json = JSON.stringify(jso);

// And now we send it off to the controller/action:
$.ajax({
  url: '@Url.Action("SomeAction","SomeController")',
  type: 'POST',
  data: json, // pass of data serialized
  dataType: 'json', // expecting json back
  contentType: 'application/json; charset=utf-8', // hey ModelBinder, deserialize this!
})/* handle the Deferred callbacks (.done, .fail, .always) */;

Then, in your controller:

public class SomeController : Controller
{
    [HttpPost]
    public JsonResult SomeAction(IList<MyModel> models)
    {
         // Should pass now
         if (ModelState.IsValid)
         {
             // Handle it and return back the response
             // Given the above, you have something like the following now
             // assigned to "models":
             // models = new List<MyModel> {
             //   new MyModel {
             //     Id = null,
             //     Start = new DateTime(2014, 11, 6, 12, 17, 52),
             //     End = new DateTime(2014, 11, 6, 12, 17, 52),
             //     Name = "test",
             //     Status = "test"
             //   }
             // };

             return Json(new {Models = models }); // just to see it come back
         }
         return Json(new { Error = true, Message = "Invalid model" });
    }
}

Working example can be seen On GitHub by the way.

Sign up to request clarification or add additional context in comments.

Comments

1

Here is a pretty simple example using POST and Json.Net to deserialize into a JObject

Get Json.Net via Nuget.

API Controller:

[HttpPost]
public dynamic UpdateItem([FromBody]dynamic item)
{
    var qp = JObject.Parse(item.ToString());
    string oid = qp.SelectToken("oid").ToString();

...

Make sure your route and param name matches an actual route, for example

config.Routes.MapHttpRoute(
   name: "ItemApi",
   routeTemplate: "api/{controller}/{action}/{item}",
   defaults: new { item = RouteParameter.Optional }
);

Usually found under App_Start/WebApiConfig.cs or in global.asax.

And then post to it using jquery ajax:

var param = new Object();
param.oid = "somestring";
param.name = "john";
param.number = 3;            
$.ajax({
    type: "POST",
    url: "/api/YourController/UpdateItem",
    data: JSON.stringify(param),
    contentType: 'application/json',
    success: function (data) {
        // do stuff
    },
    error: function (e) {
        console.error("error", e);                    
    }
});

EDIT: I see now that you are using a mvc controller. I assumed a webapi controller for my answer. Apologizes :)

6 Comments

Once again, the ModelBinder is fully capable of deserializing incoming JSON data (without the need to process it yourself in an action or (moreover) add another dependency to do so). IMHO, coming up with alternatives to deserializing the information outside of the ModelBinder adds unnecessary complexity, maintenance headaches and is just more work than is needed.
It's a matter of taste isn't it? in this solution you wouldn't have to create a poco, which can be handy and appropriate sometimes
And what if you decide to rename a property, or change a data type? Not going to have the luxury of compiler errors. Instead you wind up chasing your tail, or worse, come across the errors in production.
See my edit, I would probably use a strongly typed model if this were a strongly typed view posting to a mvc controller. As for web api, it's a matter of taste and scenario imo. I could put the property names of the dynamic object in a json schema or config... what you suggest / using poco would also work ;-)
Understood. I just feel like solidified models are the best route. Sure, they can be extra overhead (especially when you're dealing with such little pieces of information) but, then again, we'd be working in "VC" instead of "MVC" if we didn't use them. ;-) (As an aside, you'd be amazed how fast problems can manifest using dynamic. Probably one of the biggest reasons behind TypeScript given JavaScript's "looseness").
|
0

It is mvc's default behaviour it will convert json object to your C# object automatically. just makesure property name matches. Check this may help

Comments

0

For that you need to use JsonConvert.DeserializeObject() method.

Like this

List<YourModelClass> myObjList = 
(List<YourModelClass>)Newtonsoft.Json.JsonConvert.DeserializeObject(models, typeof(List<test>));

Then return this object named - myObjList to your view or whatever...

And For single object -

return JsonConvert.DeserializeObject<YourModelClass>(models);

1 Comment

Default behavior of the Modelbinder is to do this. no need for an explicit call (unless it varies greatly outside the scope of the ModelBinder, in which case you can implement your own IModelBinder)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.