ASP.NET MVC如何将JSON对象从View传递给Controller作为参数

我有一个复杂的JSON对象发送到视图没有任何问题(如下所示),但我不能解决如何将这些数据序列化回.NET对象,当它通过AJAX调用传回给控制器。 各部分的细节如下。

var ObjectA = { "Name": 1, "Starting": new Date(1221644506800), "Timeline": [ { "StartTime": new Date(1221644506800), "GoesFor": 200 } , { "StartTime": new Date(1221644506800), "GoesFor": 100 } ] }; 

我不知道如何将这个对象传递给一个控制器方法,我有下面这个方法的时间轴对象使用属性镜像上面的JS对象。

 public JsonResult Save(Timelines person) 

我正在使用的jQuery是:

  var encoded = $.toJSON(SessionSchedule); $.ajax({ url: "/Timeline/Save", type: "POST", dataType: 'json', data: encoded, contentType: "application/json; charset=utf-8", beforeSend: function() { $("#saveStatus").html("Saving").show(); }, success: function(result) { alert(result.Result); $("#saveStatus").html(result.Result).show(); } }); 

我已经看到这个问题是相似的,但不完全相同,因为我不使用表单来操纵数据。 如何使用json将复杂types传递给ASP.NET MVC控制器

我也看到使用'JsonFilter'来手动反序列化JSON的引用,但想知道是否有办法通过ASP.NET MVC本身做? 或者以这种方式传递数据的最佳实践是什么?

编辑:

MVC 3的到来不再需要这个方法,因为它会自动处理 – http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3 -preview-1.aspx


你可以使用这个ObjectFilter:

  public class ObjectFilter : ActionFilterAttribute { public string Param { get; set; } public Type RootType { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { if ((filterContext.HttpContext.Request.ContentType ?? string.Empty).Contains("application/json")) { object o = new DataContractJsonSerializer(RootType).ReadObject(filterContext.HttpContext.Request.InputStream); filterContext.ActionParameters[Param] = o; } } } 

然后,您可以将其应用于您的控制器方法,如下所示:

  [ObjectFilter(Param = "postdata", RootType = typeof(ObjectToSerializeTo))] public JsonResult ControllerMethod(ObjectToSerializeTo postdata) { ... } 

所以基本上,如果这个post的内容types是“application / json”,这将会popup一个动作,并将这个值映射到你指定的types的对象。

你说“我不使用表单来操纵数据”。 但是你正在做一个POST。 因此,实际上,即使它是空的,也使用表单。

$ .ajax的dataType告诉jQuery服务器将返回什么types,而不是你传递的是什么。 POST只能传递一个表单。 jQuery 将数据转换为键/值对并将其作为查询string传递。 从文档:

要发送到服务器的数据。 它被转换成一个查询string,如果还不是一个string。 它被附加到GET请求的URL。 请参阅processData选项以防止此自动处理。 对象必须是键/值对。 如果value是一个数组,则jQuery使用相同的键串行化多个值,即{foo:[“bar1”,“bar2”]}变成'&foo = bar1&foo = bar2'。

因此:

  1. 您没有将JSON传递到服务器。 您将JSON传递给jQuery。
  2. 模型绑定发生的方式与其他情况下发生的一样。

一个简单的jQuery插件不同

尽pipe这个问题的答案早就过时了,但是我仍然发布了一个很好的解决scheme,我之前就已经发布了,并且将复杂的JSON发送到Asp.net MVC控制器动作非常简单,因此它们被模型绑定到任何强types参数。

这个插件也支持date ,所以他们转换成他们的DateTime对手没有问题。

你可以在我的博客文章中find所有的细节,我检查问题,并提供必要的代码来实现这一点。

所有你需要做的就是在客户端使用这个插件。 Ajax请求将如下所示:

 $.ajax({ type: "POST", url: "SomeURL", data: $.toDictionary(yourComplexJSONobject), success: function() { ... }, error: function() { ... } }); 

但这只是整个问题的一部分。 现在我们可以将复杂的JSON发送回服务器,但由于它将模型绑定到可能具有属性validation属性的复杂types,因此可能会失败。 我也有一个解决scheme 。 我的解决scheme利用了jQuery Ajaxfunction,可以使结果成功或者错误(正如上面的代码所示)。 所以当validation失败时, error函数会被调用,因为它应该是。

您也可以使用JavaScriptSerializer类。 这将让你反序列化JSON到一个.NET对象。 有一个通用的Deserialize<T> ,虽然你需要.NET对象有一个类似于JavaScript的签名。 此外,还有一个DeserializeObject方法,只是一个普通的object 。 然后,您可以使用reflection来获取所需的属性。

如果你的控制器需要一个FormCollection ,并且你没有添加任何其他的data的JSON应该在form[0]

 public ActionResult Save(FormCollection forms) { string json = forms[0]; // do your thing here. } 

这个答案是跟随DaRKoN_的答案,利用对象filter:

 [ObjectFilter(Param = "postdata", RootType = typeof(ObjectToSerializeTo))] public JsonResult ControllerMethod(ObjectToSerializeTo postdata) { ... } 

我有一个问题搞清楚如何将多个参数发送到一个操作方法,并有一个是JSON对象,另一个是一个普通的string。 我是新来的MVC,我刚刚忘记了我已经解决了这个问题与非Ajax的意见。

如果我需要一个视图上的两个不同的对象,我会怎么做。 我会创build一个ViewModel类。 所以说我需要的人物和地址对象,我会做以下几点:

 public class SomeViewModel() { public Person Person { get; set; } public Address Address { get; set; } } 

然后我将视图绑定到SomeViewModel。 你可以用JSON做同样的事情。

 [ObjectFilter(Param = "jsonViewModel", RootType = typeof(JsonViewModel))] // Don't forget to add the object filter class in DaRKoN_'s answer. public JsonResult doJsonStuff(JsonViewModel jsonViewModel) { Person p = jsonViewModel.Person; Address a = jsonViewModel.Address; // Do stuff jsonViewModel.Person = p; jsonViewModel.Address = a; return Json(jsonViewModel); } 

然后在视图中,您可以使用如下简单的JQuery调用:

 var json = { Person: { Name: "John Doe", Sex: "Male", Age: 23 }, Address: { Street: "123 fk st.", City: "Redmond", State: "Washington" } }; $.ajax({ url: 'home/doJsonStuff', type: 'POST', contentType: 'application/json', dataType: 'json', data: JSON.stringify(json), //You'll need to reference json2.js success: function (response) { var person = response.Person; var address = response.Address; } }); 

回答丹的评论如下:

我正在使用这种方法来实现相同的事情,但由于某种原因,我得到一个ReadObject方法的exception:“从命名空间'期待元素'根''遇到'无'名称','命名空间''。 “ 任何想法为什么? – 丹Appleyard 4年4月6日在17:57

我有同样的问题(MVC 3构build3.0.11209.0),下面的post解决了我。 基本上,JSON串行器试图读取一个不在开始的stream,所以重新定位到0的stream固定它…

http://nali.org/asp-net-mvc-expecting-element-root-from-namespace-encountered-none-with-name-namespace/