Sending JSON to an ASP.NET MVC Action Method Argument

asp.net mvc, asp.net, code 0 comments suggest edit

UPDATE: The JsonValueProviderFactory is now registered by default in ASP.NET MVC 3. So if you’re using ASP.NET MVC 3, you can ignore that part of this blog post.

Javier “G Money” Lozano, one of the good folks involved with C4MVC, recently wrote a blog post on posting JSON (JavaScript Object Notation) encoded data to an MVC controller action. In his post, he describes an interesting approach of using a custom model binder to bind sent JSON data to an argument of an action method. Unfortunately, his sample left out the custom model binder and only demonstrates how to retrieveJSON data sent from a controller action, not how to send the JSON to the action method. Honest mistake. :)

His post reminds me of how remiss I’ve been in blogging recently because a while back, we added something to our ASP.NET MVC 2 Futures library that handles sending JSON to an action method but I just never found time to blog about it.

There’s one key problem with using a model binder to accept JSON. By writing a custom model binder, you miss out on validation. Using his example, if you type “abc” for the Age field, you will get a serialization failure when attempting to serialize the JSON into the PersonInputModel object because Age is an Int32 and the serialization will fail.

Value Providers to the rescue!

This is where value providers, a new feature of ASP.NET MVC 2, enters to save the day. Whereas model binders are used to bind incoming data to an object model, value providers provide an abstraction for the incoming data itself.

When the ASP.NET MVC feature team first implemented value providers, Jonathan Carter and I were working on a client templating sample which sent JSON to an action method. Rather than write a custom model binder which was the approach I took, Jonathan had the unique insight to write a custom value provider which received JSON data and serialized it to a dictionary rather than the target object. The beauty of his approach is that this dictionary data is then passed to the default model binder which binds it to the final object with validation!

I took is his prototype and added the JsonValueProviderFactory to our ASP.NET MVC 2 Futures library and then totally didn’t write about it. Yes, I suck.

Setting it up

To get started, download the ASP.NET MVC 2 Futures Library and reference the Microsoft.Web.Mvc.dll assembly. Then, in your Global.asax.cs file, add the following call to register the JsonValueProviderFactory.

protected void Application_Start() 
{
  RegisterRoutes(RouteTable.Routes);
  ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
}

That’s it! You’re done!

This value provider will handle requests that are encoded as application/json. There’s no need to specify a model binder on classes that accept JSON input.

See it in action

I took the liberty of updating Javier’s sample to use this new value provider and to actually post JSON to the action method.

It turns out, sending JSON encoded data to an action method with jQuery was not as straightforward as I hoped. If you know of a more straightforward way, let me know. I ended up using a JSON plug-in for jQuery I found on the Internets. This provides a $.toJSON method I could use to serialize an object into a JSON encoded string. Here’s the updated client script code.

UPDATE: Per Dave Ward’s comment here I should be using json2.js and its JSON.stringify(...) method instead because it matches an API that some browsers implement and will use the native implementation if it exists. Nice! I’ll update this blog post later when I have a moment.

$(function () {
    $("#personCreate").click(function () {
        var person = getPerson();

        // poor man's validation
        if (person == null) {
            alert("Specify a name please!");
            return;
        }

        var json = $.toJSON(person);

        $.ajax({
            url: '/home/save',
            type: 'POST',
            dataType: 'json',
            data: json,
            contentType: 'application/json; charset=utf-8',
            success: function (data) {
                // get the result and do some magic with it
                var message = data.Message;
                $("#resultMessage").html(message);
            }
        });
    });
});

function getPerson() {
    var name = $("#Name").val();
    var age = $("#Age").val();

    // poor man's validation
    return (name == "") ? null : { Name: name, Age: age };
}

Notice that we use the $.ajax method to specify both the JSON data and the JSON content type for the request.

A quick check in Fiddler confirms that the data in the POST request is properly JSON encoded.

json-request-fiddler

Now, within my action method, I can actually check to see if the model state is valid and if not, return an error message.

[HttpPost]
public ActionResult Save(PersonInputModel inputModel) {
  if (ModelState.IsValid)
  {
    string message = string.Format("Created user '{0}' aged '{1}' in the system."
      , inputModel.Name, inputModel.Age);
    return Json(new PersonViewModel { Message = message });
  }
  else {
    string errorMessage = "<div class=\"validation-summary-errors\">" 
      + "The following errors occurred:<ul>";
    foreach (var key in ModelState.Keys) {
      var error = ModelState[key].Errors.FirstOrDefault();
      if (error != null) {
        errorMessage += "<li class=\"field-validation-error\">" 
         + error.ErrorMessage + "</li>";
      }
    }
    errorMessage += "</ul>";
    return Json(new PersonViewModel { Message = errorMessage });
  }
}

And as you can see in the Fiddler screenshot, I sent an invalid Age to the server and yet, it all still works.

validation-with-json

Whew! I can finally cross this off of my immense blog backlog. :) Hopefully soon, I’ll blog a more detailed write-up of value providers.

We have plans to add the JsonValueProviderFactory to ASP.NET MVC 3 so that it’s a built-in feature. I hope you find this useful and as always, let me know if there are ways we can improve it!

Oh, and here’s Javier’s updated sample with the value provider.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

57 responses

  1. Avatar for Javier Lozano
    Javier Lozano April 14th, 2010

    Haha, great minds think a like. Someone on my blog post commented "you're not sending JSON", which the commenter (as yourself) are completely right.
    So I wrote a simple sample that does the _same_ thing you just did only without an IValueProvider, just a plain JSONModelBinder. It's here - github.com/.../JSONModelBinder
    However, your approach is much sexier and straight to the point.
    -G out :)

  2. Avatar for Felipe Lima
    Felipe Lima April 14th, 2010

    Nice to know I can use JSON input and still keep the good old model binding in the action method.
    Now, I'll just have to find out what'thahell a ValueProvider is :)

  3. Avatar for Dave Ward
    Dave Ward April 14th, 2010

    Consider using json2.js instead of the $.toJSON() plugin. Its JSON.stringify() does the same thing.
    The benefit of going that way is that browsers have duplicated json2.js' API in their browser-native JSON handling, and json2.js only defines its functions if the JSON object doesn't already exist. So in newer browsers, JSON.stringify() will automatically call the browser-native method.

  4. Avatar for haacked
    haacked April 14th, 2010

    Thanks Dave! When I get a chance I'll update my blog post. Thanks for the tip!

  5. Avatar for Mike Sampson (Sampy)
    Mike Sampson (Sampy) April 15th, 2010

    I just wrote a custom value provider earlier this week actually. Mine offers up properties of the HttpRequest object (referrer, ip address, and user agent) for binding to anything that ends with the right string (so that way it can cheat a little bit for deeply nested objects that need those properties).
    I use it to collect data for anonymous comments as well as for forum posts so we can do things like IP bans and looking for people with multiple accounts.
    Handy new feature!

  6. Avatar for Sergejus
    Sergejus April 15th, 2010

    Phill,
    I would also suggest for the getPage() function to use jQuery serialize method (http://api.jquery.com/serialize) instead of doing .val() manually.

  7. Avatar for Adam
    Adam April 15th, 2010

    What is the advantage of doing this?
    If you call $.ajax and pass a json object to the data parameter it will convert it to key/value pairs and the default model binder will take care of the binding. It seems that you are doing more worked than is needed.
    Unless of course I'm missing something.

  8. Avatar for Bob Cravens
    Bob Cravens April 16th, 2010

    Why convert it to JSON on the client? Does the added complexity buy you something? Maybe you save a few bytes on the wire. When the data pops out the other side, it is converted to the model before your controller gets a whack at it. Why not keep it simpler:

    var url = "/home/save";
    var name = $("#Name").val();
    var age = $("#Age").val();
    $.post(url, { Name: name, Age: age }, function(data) {
    var message = data.Message;
    $("#resultMessage").html(message);
    });

    Same question for the return type. Why return JSON? In this case, it is a simple string. Why not just return the string.
    Am I missing something?
    Here is a simple to complex run down on Ajax calls to MVC controllers: blog.bobcravens.com/...

  9. Avatar for haacked
    haacked April 16th, 2010

    Why do it this way? Well in this specific case, I probably wouldn't. This was a contrived example. The real point of this post is to demonstrate how to receive JSON encoded data as an argument to your action method. Why?
    If you were using the ASP.NET Ajax client templating preview, it sends objects to an URL as JSON objects. This solution I showed would allow you to connect client templates to an MVC URL. Other client templating solutions might do that.
    Also, you can imagine an action method with this in place could support multiple clients: an HTML form posting form encoded data, a silverlight widget posting JSON, etc...

  10. Avatar for Shamol
    Shamol April 16th, 2010

    we are using Action Filter to do this for quite some time now. ( we do our validation on another tire). i wonder if my approach has any negative side to it?

  11. Avatar for Michael McGuire
    Michael McGuire April 17th, 2010

    I must say, as the commenter on Javier's blog, that I giggled like a little girl when it appeared to inspire this blog post. Of course, I know you were already planning on doing it, but still.
    Thanks for taking the time to discuss this issue Phil, I've been wondering what was a good way way to get JSON passed to an MVC Action method.

  12. Avatar for Justin
    Justin April 17th, 2010

    Thanks Phil,
    Until now I have been binding the input as a string then using a JavaScript Serializer to transform it to my input model. This is so much easier.

  13. Avatar for Erik
    Erik April 21st, 2010

    This is just what I've been looking for! But I can't find the actual code in the MvcFutures folder in the codeplex source?! Could you point me in the right direction?

  14. Avatar for John McDowall
    John McDowall April 26th, 2010

    The Value provider doesn't seem to reserialise certain characters correctly, such as the @ symbol used in an email address. Is this expected?

  15. Avatar for Mike
    Mike April 28th, 2010

    What is the json value provider using on the back end? Is it fully capable of binding json to complex object types (objects that have properties that are lists or that are other objects)?

  16. Avatar for Ben
    Ben May 1st, 2010

    The JsonValueProviderFactory is great.
    However (isn't is always a "however"), when I try to add an AntiForgeryToken to my data, I get a response back that my AntiForgeryToken was missing or invalid.
    Even if I submit only the __RequestVerificationToken in the data, I still get this message using the JsonValueProviderFactory.
    Has anyone else come across this? Any suggestions?

  17. Avatar for Richard Garside
    Richard Garside May 11th, 2010

    Is there a similar way to send XML to an MVC action method?
    I'm creating an API and I want the API user to be able to use either json or xml.

  18. Avatar for JJ
    JJ May 15th, 2010

    How can I tell if it is executing the JsonValueProviderFactory or not?
    My JSON.stringify(...) method produces this string:
    "{"Id":"3","OrderStatus"...Z","Comments":"rtgdds"}"
    Is that the correct format? In my action, the POCO object is not null, but all of its fields are null

  19. Avatar for JJ
    JJ May 16th, 2010

    Why is it, that in order to send a json object to a controller method, you have to manually change the content type?
    Ie, why does MVC not work out of the box with the default content type of application/x-www-form-urlencoded?

  20. Avatar for haacked
    haacked May 16th, 2010

    We do work with application/x-www-form-urlencoded when you are sending form urlencoded data to the webserver.
    But JSON Serialized data is not the same as form urlencoded data. The point of this post is how to send JSON encoded data as the BODY of your HTTP Post request and not in a form field. In that case, you need to change the content type.

  21. Avatar for Fabio Maulo
    Fabio Maulo May 21st, 2010

    This example fabiomaulo.blogspot.com/... do that in WebForms.
    The method Publica(ClasificadoInfo clasificado) is the one receiving the POST in Json and transform it to an obj graph using a convention.

  22. Avatar for Michael Reyeros
    Michael Reyeros June 23rd, 2010

    Good evening Phil, I tried implementing this code in a project that I working on but for some reason when the model gets to my ActionMethod for some reason decimal properties are being set to 0 although they have a different value and if I view the page source I can see the correct values are being passed to the stringify function. Here is the javascript code as it looks when it hits the page:
    $("#VehicleModelId1").change(function () {
    var model = $("#VehicleModelId1 > option:selected").attr("value");
    $("#imgModel1").attr('src', "GetModelImage/" + model);
    var services = $.toJSON([{"MobileProviderServiceId":1,"ServiceName":"Basic Service","SmallVehicleCost":15.00,"MediumVehicleCost":20.00,"LargeVehicleCost":25.00,"SmallVehicleDuration":15,"MediumVehicleDuration":20,"LargeVehicleDuration":25}]);
    $.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    url: "GetServicesBasedOnModel/" + model,
    data: services,
    dataType: "json",
    async: true,
    success: function (data) {
    var serviceWrapper = $("#serviceWrapper1 > ul");
    if (data) {
    serviceWrapper.html(data.services);
    }
    else
    serviceWrapper.html('');
    }
    });
    });
    When I set a breakpoint at my action method, the cost properties are all equal to 0 but the duration properties which are integer properties on my model, all have their correct values.
    Hopefully you can lead me in the right direction.

  23. Avatar for Richard Garside
    Richard Garside July 15th, 2010

    Inspired by this article I created an XML Value Provider. It's based on your source code. I've put the code on my site so hopefully other people will find it useful.
    XML Value Provider

  24. Avatar for Daniel Steigerwald
    Daniel Steigerwald August 11th, 2010

    JSON.stringify({ Updated: new Date() });
    Doesn't work.

  25. Avatar for Daniel Steigerwald
    Daniel Steigerwald August 11th, 2010

    More precisely, it doesn't work for get request.

  26. Avatar for Chris
    Chris August 18th, 2010

    I've had a few problems when using this method. First. what data types do these value providers map and how do they work really? I'm having problems mapping a return of a JSON Date to a DateTime field in my View Model. Also decimals don't seem to map when sending a 1.0 or even a "1.0". Lastly When sending over mildly large collections (200 entries 8 fields each) It takes us about 5 minutes for the controller to hit it's first break point. I am assuming this is because the data binding is taking forever (small collections work well). Any idea or insight?

  27. Avatar for Randy Roesler
    Randy Roesler September 3rd, 2010

    Daniel, Chris: I also can not send Date(times) (formatted as)
    \/Date(ticks)\/ in AJAX requests
    The server always seem to receive '"\\/Date(' rather than '"\/Date('
    I can not seem to get the extra (quoting) back-slash out of my javascript.

  28. Avatar for Johan van Heerden
    Johan van Heerden September 5th, 2010

    Thanks for the post Phil,
    Like Michael Reyeros I too have problems with the deserialization of the JSON response. The properties of the object I receive in my action method are not set. When I use my own model binder and leave out the value provider the properties are all set. I would like to have the validation, but it seems I can't use both the value provider and a custom model binder.
    Any help/ideas would be greatly appreciated.

  29. Avatar for PT
    PT September 9th, 2010

    So, I downloaded the MVC Futures package, extracted the DLL, referenced it gingerly in my project, added the global.asax.cs line, and joyfully proceed to send JSON messages to a method on my PatientController, craefully named public ActionResult Update(PatientDirectoryRecord record)
    However, when I debug the method, the this.Binders dictionary makes no mention of any JSON binder/value provider. I see the DefaultModelBinder, HttpPostedFileBaseModelBinder, ByteArrayModelBinder and LinqBinaryModelBinder. And, the JSON message is not being bound to record. Actually, the "id" field seems to get in there, but all others are null.
    Any ideas?

  30. Avatar for PT
    PT September 10th, 2010

    Another question: When I add the value provider in global.asax.cs, this bit of code fails to return the JSON embedded in the Request's body:
    public ActionResult Update(PatientDirectoryRecord record)
    {
    ...
    var sr = new StreamReader(Request.InputStream);
    var requestBody = sr.ReadToEnd();
    ...
    }
    If I comment out the Add(new JsonValueProviderFactory()) line, then my JSON in the request is avalable to the StreamReader in the controller method.
    Why?

  31. Avatar for Sachin
    Sachin October 22nd, 2010

    I have action method like
    public ActionResult Save(Dictionary<string, string> dicObject)
    I want to pass JSON as dictionary object but dictObject gives always null
    I have added JSON Factory to global.asax
    What i have to do? I have to create custom JSON Factory or any thing else?
    Can any one help me, its urgent
    Thanks for hep

  32. Avatar for Zachary Scott
    Zachary Scott October 24th, 2010

    Wow, this was immensely beneficial in understanding and implementing JSON conversations with MVC 2. Thank you very much.

  33. Avatar for Sajib
    Sajib November 7th, 2010

    AntiForgeryToken is not working for me as well. I tried adding
    "__RequestVerificationToken" in the data and used JSON.stringify method to stringify the data.
    Hi Ben, did you get any solution or anyone has found any solution?
    Please post here if yes.

  34. Avatar for Tyler
    Tyler November 10th, 2010

    I killed myself for 2 days figuring this out, so thought I would share.
    By default a javascript array object turned JSON looks like this:
    {"0":{"Name":"Cup Warmer","Id":1,"Price":10,"Quantity":0},
    "1":{"Name":"Hello Kitty Mug","Id":2,"Price":20,"Quantity":0},
    "2":{"Name":"Percolator","Id":3,"Price":50,"Quantity":0},
    "3":{"Name":"A Bunch of Coffee","Id":4,"Price":100,"Quantity":0}}
    But for the binder to work it needs some help to know that "0" belongs at the "0" index of my object. If instead of building up your array with just "0" as the index you use the parameter name of your controller it flies.
    Controller Signature:
    public ActionResult Submit(IEnumerable<OrderInfo> productList)
    Javascript:
    function SubmitOrder() {
    var productData = {};
    var productList = $('#productList li')
    productList.each(function(index, element) {
    var productInfo = $(element).data('ProductInfo');
    productData['productList[' + index + ']'] = productInfo;
    });
    $.ajax({
    'url': 'order/submit',
    'type': 'post',
    'data': JSON.stringify(productData),
    'dataType': 'json',
    'contentType': 'application/json; charset=utf-8'
    }
    );
    }
    The key is "productData['productList[' + index + ']'] = productInfo". This will output a JSON object that the binder can work with.
    {"productList[0]" : {"Name":"Cup Warmer", "Id":1, "Price":10, "Quantity":1},
    "productList[1]":{"Name":"Hello Kitty Mug","Id":2,"Price":20,"Quantity":1},
    "productList[2]":{"Name":"Percolator","Id":3,"Price":50,"Quantity":1},
    "productList[3]":{"Name":"A Bunch of Coffee","Id":4,"Price":100,"Quantity":2}}
    Boo yah!!

  35. Avatar for Ryan
    Ryan November 30th, 2010

    Is there anything similar for XML? At first glance, it seemed like it wouldn't be that hard to implement since we would just need to deserialize from XML instead of JSON, but I can't find a method that's comparable to JavaScriptSerializer.DeserializeObject(string input) - does one exist?

  36. Avatar for Robert Koritnik
    Robert Koritnik December 27th, 2010

    This technique is smart but requires changes on both the client and server. I've used a different approach that's MVC any version compatible. And it only requires client change by using a custom jQuery plugin that transforms your Javascript objects into something that's easily and correctly posted back to server.
    Check my blog post about it with extensive explanation how it works.
    erraticdev.blogspot.com/...

  37. Avatar for Sam
    Sam January 6th, 2011

    Loved this on paper. However, when trying to use it can't parse MS's own date literals. This should both ways... I return JSON to the browser using the Json view method which sent: "PolicyStartDate":"/Date(1294318800000)/"
    However this only semi helpful value provider when receiving this fails and I just get DateTime.MinValue as the value of PolicyStartDate. Really really really sick of dates and ajax.

  38. Avatar for Robert Koritnik
    Robert Koritnik January 7th, 2011

    @Sam: Check my aforementioned blog post with a short jQuery plugin that simplifies sending complex JSON objects to Asp.net MVC. Including dates. ;)
    But regarding the other way around when receiving JSON data in the browser I've also written an extension for jQuery that makes it possible to automatically convert dates in JSON strings by simply using $.parseJSON(). Anyway. Head over to blog post and read it.

  39. Avatar for W3Max
    W3Max January 18th, 2011

    The feature is great but I think there is some bugs.
    I didn't try dates but arrays are always null.
    Example: {Id:1,Children:[1,2,3]}
    Anyone having the same problem?

  40. Avatar for Robert Koritnik
    Robert Koritnik January 19th, 2011

    @W3Max: I suggest you try my jQuery plugin that makes it possible to send complex JSON objects (not strings) to Asp.net MVC without adding functionality on both the client and server side. This is just a rather simple client-side plugin that converts a JSON object into a dictionary-like structure that jQuery Ajax functionaly can easily consume and Asp.net MVC understands. Even nested objects, arrays and dates. Everything goes. And works.
    (@everyone-else: In my previous comment I've accidentally linked to Phil Haack's blog post instead to mine. First link in that comment should be the same as this one above here.)

  41. Avatar for Gautam Jain
    Gautam Jain April 1st, 2011

    Please do help.
    The JsonValueProviderFactory is not binding types such as Color, Position, Point. In short, all non-primitive objects. It is able to bind integer, string and also arrays of these types.
    What am I doing wrong?
    My json data is:
    {
    "Name":"Pen",
    "Type":1,
    "DeviceSize":{"Width":190,"Height":180}
    }
    DeviceSize is of type Size. Similarly I have other properties of type Color, Point etc. Name & Type is correctly bound. But DeviceSize is not bound.
    Thanks.
    Regards,
    Gautam Jain

  42. Avatar for suresh
    suresh May 22nd, 2011

    Hi,
    If any one has worked on Collection/Array with JSON can you share the solution of the same

  43. Avatar for ahura mazda
    ahura mazda June 9th, 2011

    I had the same issue; I could not get JSON Arrays or .NET Enums to serialize/deserialize.
    However, I found a solution using Json.NET. See my blog post on how to implement it

  44. Avatar for Sujith
    Sujith July 4th, 2011

    Hi,
    Have anyone of you worked on validating JSON using webtest?(ie, in its response or atleast if it is poosible?)

  45. Avatar for Sam
    Sam July 24th, 2011

    Jsonvalueprovider (or something) seems to have dropped the ball on globalization.
    In my scenario I submit a form with ajax. The value submitted is 'sov=0,1'. My model has a decimal property called SOV. Json will NOT bind this value. If I change it to 0.1 it will. Effectively making using this in a globalized app a nightmare.

  46. Avatar for Bohemian
    Bohemian July 29th, 2011

    Great article, works with MVC 2 and MVC 3 but I seem to be having an issue that I hope you (Phil Haack) or somebody else may have run across or have suggestions on...
    Basically, if I create a stand-alone model as is done herein with the PersonInputModel I can access the Name & Age values just fine from the Save ActionResult via the inputModel parameter...
    But, if i use a class derived from a base class that looks like this...
    // Summary:
    // Base class used to create ViewModel objects that contain the Model object
    // and related elements.
    //
    // Type parameters:
    // T:
    // Type of the Model object.
    public abstract class ViewModelBase<T> : IViewModel where T : class
    {
    protected ViewModelBase();
    // Summary:
    // Gets or sets the Model object.
    public T ModelObject { get; set; }
    }
    derived class looks like this...
    [Serializable]
    public class DerivedInputModel : Test.Web.Mvc.ViewModelBase<PersonInputModel>
    {
    ...
    }
    age and name are set in view viz...
    <%: Html.DisplayTextFor(model => model.ModelObject.Age)%>
    <%: Html.DisplayTextFor(model => model.ModelObject.Name)%>
    when my Save ActionResult uses DerivedInputModel as a parameter JSON/MVC Futures/MVC Framework does not send/find any values for Age/Name...
    basically, while the DerivedInputModel gets to the save action result everything is null...

  47. Avatar for Hvm
    Hvm August 25th, 2011

    function OnClickAdd(mode, id) {
    debugger;
    var dataobject = new Object();

    //var test = new Array();
    if (id == 'Military') {
    dataobject.Branch = document.getElementsByName('txtBranch')[0].value;
    dataobject.Duties = document.getElementsByName('txtBranch')[0].value;
    }
    var selectedTabIndex = 0;
    $.ajax({
    type: 'Post',
    url: "/CBiography/LoadView",
    data: { "id": id, "selectedTabIndex": selectedTabIndex, "Mode": mode, "DataObject": dataobject },
    datatype: 'html',
    success: function (data) {
    if (selectedTabIndex == 0) {
    $("#Edit")[0].innerHTML = data;
    $.fn.sfEvalScripts(data);
    }
    else {
    $("#View")[0].innerHTML = data;
    $.fn.sfEvalScripts(data);
    }
    }
    });
    this is my script and i have one controller action like
    public ActionResult LoadView(string id, int? selectedTabIndex, PagingParams args, int? Mode, object DataObject)
    {
    }
    but i cant get DataObject value i also try to run your code but not working
    thanks

  48. Avatar for Sergiy Shumakov
    Sergiy Shumakov November 26th, 2011

    Hi Phil, nice blog post, it has helped me a lot :).
    Guy with comment title "Handling Arrays...weird but cool." described one issue regarding sending arrays to the controller action.
    For instance if you send array with indexes [0], [1] etc., Controller action won't recieve parsed array, instead you have to made array like array["arg0"], array["arg1"], where arg is parameter of controller. Here is sample signature:
    public ActionResult Action(List<SomeModel> arg){}
    Can ASP .NET MVC team fix this issue in future release? :)
    Thank You,
    Sergiy Shumakov,
    MSP Ukraine

  49. Avatar for DalSoft
    DalSoft January 11th, 2012

    I've blogged about how to improve on the JsonValueProviderFactory to allow you to bind to dynamic properties in your model.
    www.dalsoft.co.uk/...

  50. Avatar for chinthana
    chinthana July 5th, 2012

    great article
    my problem is security issues.because user can see all the our client side implementation.eg
    $(function () {
    $("#personCreate").click(function () {
    var person = getPerson();
    // poor man's validation
    if (person == null) {
    alert("Specify a name please!");
    return;
    }
    var json = $.toJSON(person);
    $.ajax({
    url: '/home/save',
    type: 'POST',
    dataType: 'json',
    data: json,
    contentType: 'application/json; charset=utf-8',
    success: function (data) {
    // get the result and do some magic with it
    var message = data.Message;
    $("#resultMessage").html(message);
    }
    });
    });
    });
    so.how do we build more secure application in asp.net mvc

  51. Avatar for EnChikiben
    EnChikiben July 26th, 2012

    А как можно эмулировать массив?

  52. Avatar for juve
    juve August 9th, 2012

    PTM no funcionaaaaa

  53. Avatar for Reza Baiat
    Reza Baiat August 26th, 2012

    I had problem with arrays and sub-objects. so I wrote this method after your notes in haacked.com/.../model-binding-to-a-list.aspx

    var obj = {
    id: 89,
    name: 'reza baiat',
    con: [
    8,
    'rahim',
    {
    a: 9,
    b: 6,
    points:{
    x: 4,
    y: [5,6,7,8]
    }
    },
    {
    a: 10,
    b: 11,
    points:{
    x: 12,
    y: [13,14,15,16]
    }
    }
    ]
    };

    function getPostData(obj, prefix) {
    var result = '', type = '', aType = '';
    for (var prop in obj) {
    type = typeOf(obj[prop]);
    if (type == 'string' || type == 'number' || type == 'boolean') {
    result += '&' + (prefix || '') + prop + '=' + encodeURIComponent(obj[prop]);
    } else if (type == 'object') {
    result += '&' + getPostData(obj[prop], (prefix || '') + prop + '.');
    } else if (type == 'array') {
    for (var i = 0; i < obj[prop].length; i++) {
    aType = typeOf(obj[prop][i]);
    if (aType == 'number' || aType == 'string' || aType == 'boolean') {
    result += '&' + (prefix || '') + prop + '[' + i + ']=' + encodeURIComponent(obj[prop][i]);
    } else if (aType == 'object') {
    result += '&' + getPostData(obj[prop][i], (prefix || '') + prop + '[' + i + '].');
    } else if (aType == 'array') {
    }
    }
    }
    }
    if (result.length > 0) {
    result = result.substring(1);
    }
    return result;
    }
    alert(getPostData(obj));
    // result:
    /*
    id=89&name=ali%20reza%20hasani&con[0]=8&con[1]=rahim&con[2].a=9&con[2].b=6&con[2].points.x=4&con[2].points.y[0]=5&con[2].points.y[1]=6&con[2].points.y[2]=7&con[2].points.y[3]=8&con[3].a=10&con[3].b=11&con[3].points.x=12&con[3].points.y[0]=13&con[3].points.y[1]=14&con[3].points.y[2]=15&con[3].points.y[3]=16
    */

    post getPostData(obj) to server. It will be mapped as you want. It is not complete but may help you

  54. Avatar for Aracen74
    Aracen74 December 27th, 2012

    You Rock !

  55. Avatar for Stu Gardner-Vaughan
    Stu Gardner-Vaughan February 26th, 2013

    Always a pleasure reading your posts Phil - another gem and just what I was after.

    Cheers, Stu

  56. Avatar for zhangwei
    zhangwei October 28th, 2013

    Hi,I have a problem,When I write Controllers in a single Class library so How Can I get the url to get the data,

    eg:

    $.ajax({
    url: '/home/save',//You know the url don't to get data ,Can you help me?
    type: 'POST',
    dataType: 'json',
    data: json,
    contentType: 'application/json; charset=utf-8',
    success: function (data) {
    // get the result and do some magic with it
    var message = data.Message;
    $("#resultMessage").html(message);
    }
    });

  57. Avatar for Harry McIntyre
    Harry McIntyre February 15th, 2018

    I've created a ModelBinder for doing this in ASP.NET Core - https://github.com/mcintyre...