【问题标题】:Passing dynamic json object to C# MVC controller将动态 json 对象传递给 C# MVC 控制器
【发布时间】:2011-02-16 22:31:41
【问题描述】:

我正在使用 .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 对象。当它发生变化时,我不希望每次 JSON 对象发生变化时都向我的 C# 模型添加项目。

这真的可能吗?我尝试将对象映射到字典,但数据的值最终会为空。

谢谢

【问题讨论】:

标签: jquery json asp.net-mvc-3


【解决方案1】:

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

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

【讨论】:

  • 太棒了,这样一个简单而有效的答案。谢谢
  • 如果传回的对象有子对象,这个解决方案会变得非常混乱。
  • @ChrisMoschini 如果对象有子对象,你会怎么做?
  • @user1477388 包装的动态方法:stackoverflow.com/a/17050505/176877
  • 为什么不将对象作为原始 JSON 字符串传回,例如JsonResult JsonAction(string json) 并使用 NewtonSoft Json.NET 反序列化为动态对象?
【解决方案2】:

如果您使用这样的包装器,您可以提交 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。谢谢。
【解决方案3】:

另一种解决方案是在模型中使用动态类型。我写了一篇关于如何使用 ValueProviderFactory http://www.dalsoft.co.uk/blog/index.php/2012/01/10/asp-net-mvc-3-improved-jsonvalueproviderfactory-using-json-net/ 绑定到动态类型的博文

【讨论】:

  • 如果您创建一个虚拟类来充当您要传回的动态 ViewModel 的包装器对象,该解决方案可以干净地工作,并为发送到服务器的实际数据提供一个动态属性。 Controller 的参数需要是一个实际的类,但由于它的任何子类都可以是动态的,因此您可以使用虚拟包装器解决此限制。
【解决方案4】:

类似于 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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-05
    • 1970-01-01
    • 2012-01-16
    • 2017-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多