Passing dynamic json object to C# MVC controller

2019-01-09 12:28发布

问题:

I am doing some work with .Net 4, MVC 3 and jQuery v1.5

I have a JSON object that can change depending on which page is calling it. I'd like to pass the object to a controller.

{ id: 1, title: "Some text", category: "test" }

I understand that if I create a custom model such as

[Serializable]
public class myObject
{
    public int id { get; set; }
    public string title { get; set; }
    public string category { get; set; }
}

and use this in my controller such as

public void DoSomething(myObject data)
{
    // do something
}

and pass the object using jQuery's .ajax method like this:

$.ajax({ 
    type: "POST", 
    url: "/controller/method", 
    myjsonobject,  
    dataType: "json", 
    traditional: true
});

This works fine, my JSON object is mapped to my C# object. What I'd like to do is pass through a JSON object that's likely to change. When it changes I don't want to have to add items to my C# model each time the JSON object changes.

Is this actually possible? I tried mapping objects to a Dictionary but the value of data would just end up being null.

Thanks

回答1:

Presumably the action that accepts input is only used for this particular purpose so you could just use the FormCollection object and then all your json properties of your object will be added to the string collection.

[HttpPost]
public JsonResult JsonAction(FormCollection collection)
{
    string id = collection["id"];
    return this.Json(null);
}


回答2:

You can submit JSON and parse it as dynamic if you use a wrapper like so:

JS:

var data = // Build an object, or null, or whatever you're sending back to the server here
var wrapper = { d: data }; // Wrap the object to work around MVC ModelBinder

C#, InputModel:

/// <summary>
/// The JsonDynamicValueProvider supports dynamic for all properties but not the
/// root InputModel.
/// 
/// Work around this with a dummy wrapper we can reuse across methods.
/// </summary>
public class JsonDynamicWrapper
{
    /// <summary>
    /// Dynamic json obj will be in d.
    /// 
    /// Send to server like:
    /// 
    /// { d: data }
    /// </summary>
    public dynamic d { get; set; }
}

C#, Controller action:

public JsonResult Edit(JsonDynamicWrapper json)
{
    dynamic data = json.d; // Get the actual data out of the object

    // Do something with it

    return Json(null);
}

Annoying to add the wrapper on the JS side, but simple and clean if you can get past it.

Update

You must also switch over to Json.Net as the default JSON parser in order for this to work; in MVC4 for whatever reason they've replaced nearly everything with Json.Net except Controller serialization and deserialization.

It's not very difficult - follow this article: http://www.dalsoft.co.uk/blog/index.php/2012/01/10/asp-net-mvc-3-improved-jsonvalueproviderfactory-using-json-net/



回答3:

Using a custom ModelBinder, you could receive a JsonValue as an action parameter. This would basically give you a dynamically typed JSON object that can be created on the client with whatever shape you wish. This technique is outlined in this blog post.



回答4:

Another solution is to use a dynamic type in your model. I've written a blog post about how to bind to dynamic types using a ValueProviderFactory http://www.dalsoft.co.uk/blog/index.php/2012/01/10/asp-net-mvc-3-improved-jsonvalueproviderfactory-using-json-net/