将动态json对象传递给C# MVC控制器

12

我正在使用 .Net 4、MVC 3 和 jQuery v1.5 进行一些工作。

我有一个 JSON 对象,它可以根据调用它的页面而发生变化。我想将该对象传递给控制器。

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

我理解如果我创建了一个自定义模型,比如

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

我可以在我的控制器中这样使用:

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

然后使用jQuery的.ajax方法传递对象,代码如下:

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

这段代码运行良好,我的 JSON 对象已经映射到了 C# 对象。我想要做的是传递一个可能会发生变化的 JSON 对象。当它发生变化时,我不想每次都需要向我的 C# 模型添加项目。

这是否真的可行?我尝试将对象映射到 Dictionary,但数据的值最终只会变成 null。

谢谢


相关/重复的问题:http://stackoverflow.com/questions/5473156/how-to-get-a-dynamically-created-json-data-set-in-mvc-3-controller http://stackoverflow.com/questions/10787679/passing-unstructured-json-between-jquery-and-mvc-controller-actions - Chris Moschini
5个回答

17

假设接受输入的操作仅用于这种特定目的,因此您可以使用 FormCollection 对象,然后您对象中的所有 JSON 属性将添加到字符串集合中。

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

太棒了,如此简单而有效的答案。谢谢。 - Gareth Hastings
4
如果返回的对象有子对象,那么这个解决方案会变得相当混乱。 - Chris Moschini
@ChrisMoschini 如果对象有子对象,您会怎么做? - user1477388
2
@user1477388 包装动态方法:https://dev59.com/mG445IYBdhLWcg3wIGx9#17050505 - Chris Moschini
为什么不将对象作为原始的JSON字符串返回,例如 JsonResult JsonAction(string json) 并使用NewtonSoft Json.NET反序列化为动态对象呢? - ProfK

9
您可以使用类似以下包装器来提交JSON并将其解析为动态内容:

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#,输入模型:

/// <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#,控制器操作:

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

    // Do something with it

    return Json(null);
}

在JS端添加包装器可能有点烦人,但是如果您能克服它,这种方法既简单又清晰。

更新

为了使其工作,您还必须切换到Json.Net作为默认的JSON解析器。 在MVC4中,由于某种原因,他们几乎用Json.Net替换了所有内容,除了控制器序列化和反序列化。

这并不是很困难-按照这篇文章进行操作: http://www.dalsoft.co.uk/blog/index.php/2012/01/10/asp-net-mvc-3-improved-jsonvalueproviderfactory-using-json-net/


很好,如果这个能行那就太完美了。如果这个行得通的话,就不用使用JSON.Net了。谢谢。 - user1477388

2

1
如果您创建一个虚拟类来充当包装器对象,将动态ViewModel传递回去,并具有一个用于发送到服务器的实际数据的动态属性,则此解决方案可以干净地工作。控制器的参数需要是一个实际的类,但由于它的任何子元素都可以是动态的,因此您可以使用虚拟包装器绕过此限制。 - Chris Moschini

2

与FormCollection的被接受答案类似,动态对象也可以映射到任意JSON。

唯一的注意点是您需要将每个属性转换为预期类型,否则MVC会抱怨。

例如,在TS / JS中:

最初的回答

var model: any = {};
model.prop1 = "Something";
model.prop2 = "2";

$http.post("someapi/thing", model, [...])

MVC C#:

[Route("someapi/thing")]
[HttpPost]
public object Thing(dynamic input)
{
    string prop1 = input["prop1"];
    string prop2 = input["prop2"];

    int prop2asint = int.Parse(prop2);

    return true;
}

0

这是我针对 .NET 6 使用 System.Text.Json 的解决方案

json(示例)

{
  "active": true,
  "name": "string",
  "counter": 211
}

控制器

[HttpPost]
public async Task<ActionResult> RecieveAsync(
    [FromBody] JsonObject dataObject,
    CancellationToken cancellationToken = default)
{
    if (dataObject.ContainsKey("active"))
    {
        var active = dataObject["active"].AsValue();
    }

    var myCustomObject = JsonSerializer.Deserialize<MyCustomObject>(dataObject);

    return StatusCode(StatusCodes.Status204NoContent);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接