ASP.Net MVC : Sending JSON to Controller
Asked Answered
M

1

9

I want to be able to send JSON as opposed to the standard QueryStrings when making a post to my controllers in ASP.Net MVC. I have the Front-End stuff working fine (building and then submitting my JSON objects).

The problem is on the controller side where the default ModelBinders that ship with the MVC framework do not support this.

I have seen a combination of ways around this, one of them is to apply a filter which takes the object as a parameter, uses a JSON library to de-serialise it, and adds that to the action parameters. This is not ideal.

The other, better, way is to use a custom Model Binder. All the ones I have seen though presume you will have only one model and that will be a class rather than a variable. If you have multiple ones it breaks down.

Has anyone else encountered this? One idea I had was if I could simply override how MVC deals with the FormCollection and intercept there, adding the values to the collection myself and hoping MVC can do the rest in it's normal fashion. Does anyone know if that is possible?

The key issue, I think, is that my problem is not with binding because my view models are no different to how they where before. The problem is getting the values from the JSON Post.

If I am correct MVC get's the values from the QueryString and puts it into the form collection which is then used for ModelBinding. So shouldn't the correct method be to change the way the FormCollection gets assigned?

Example of an action:

public ActionResult MyFirstAction(Int32 ID, PersonObject Person, ClassObject ClassDetails)
{
//etc
}

The normal binding works, JSON doesn't and all the example of Model Binders will not work either. My best solution so far is to convert the object to a dictionary and loop though each param and match it up. Doesn't seem ideal.

Minicam answered 26/1, 2010 at 16:35 Comment(5)
If your going to vote this down could you explain why?Minicam
Sorry, unfortunately, when I went to click the favorite star, I accidentally clicked the down vote, even after I already upvoted it (that's why it went from 5 to 3). And now it said immediately after trying to undo what I accidentally did, that it was too late to change my vote, unless the question gets editted. If you make an edit to the question I'll gladly fix my vote.Ervin
No problem! That happens to me as well many a time.Minicam
I don't know what's going on, but it's still not letting me fix my vote.Ervin
Nah it's fine. Don't worry about it. I don't really mind if someone votes me down as long as I know why, turned out to be a bug anyway.Minicam
B
8

I use a custom model binder for json like this:

public class JsonModelBinder<T> : IModelBinder {
    private string key;

    public JsonModelBinder(string requestKey) {
        this.key = requestKey;
    }

    public object BindModel(ControllerContext controllerContext, ...) {
        var json = controllerContext.HttpContext.Request[key];
        return new JsonSerializer().Deserialize<T>(json);
    }
}

And then wire it up in Global.asax.cs like this:

ModelBinders.Binders.Add(
    typeof(Product),
    new JsonModelBinder<Product>("ProductJson"));

You can read more about this here: Inheritance is Evil: The Epic Fail of the DataAnnotationsModelBinder

EDIT

The JsonModelBinder should be used on the controller action parameter typed as Product only. The Int32 and ClassObject should fall back to the DefaultModelBinder. Are you experiencing a different result?

Barnstorm answered 26/1, 2010 at 16:42 Comment(6)
So you would need to define which types to use it for?Minicam
Yes, you have to specify the types. Can you describe your situation in a little more detail? I have been digging into model binding more lately and there is a lot of non-obvious functionality in it.Barnstorm
Well with the types what do I do about action parameters which are primitive types/stings? If I am sending Int32 ID, Class Product it creates a problemMinicam
Can you update your question with an example controller action?Barnstorm
No Problemo! Added it. Cheers.Minicam
Yes, I am (experiencing a different result). Basically the JSON object that gets sent to the action is not populating anything. If I sent { "ID" : 34 } and ID was the only action it won't get mappped. These are normal entities, it's just that I want to send the data via JSON and MVC doesn't understand it.Minicam

© 2022 - 2024 — McMap. All rights reserved.