如何使用 json 将复杂类型传递给 ASP.NET MVC 控制器
Posted
技术标签:
【中文标题】如何使用 json 将复杂类型传递给 ASP.NET MVC 控制器【英文标题】:How to pass complex type using json to ASP.NET MVC controller 【发布时间】:2010-09-21 00:41:54 【问题描述】:我有一个视图,允许用户输入/编辑新窗口小部件的数据。我想将该数据形成一个 json 对象并通过 AJAX 将其发送到我的控制器,这样我就可以在服务器上进行验证而无需回发。
我已经完成了所有工作,只是我不知道如何传递数据,因此我的控制器方法可以接受复杂的 Widget 类型,而不是每个属性的单独参数。
所以,如果这是我的对象:
public class Widget
public int Id get; set;
public string Name get; set;
public decimal Price get; set;
我希望我的控制器方法看起来像这样:
public JsonResult Save(Widget widget)
...
目前,我的 jQuery 看起来像这样:
var formData = $("#Form1").serializeArray();
$.post("/Widget/Save",
formData,
function(result), "json");
我的表单 (Form1) 为 Widget 上的每个属性(Id、Name、Price)都有一个输入字段。这很好用,但它最终将 Widget 的每个属性作为单独的参数传递给我的控制器方法。
有没有一种方法可以“拦截”数据,可能使用 ActionFilterAttribute,然后在调用控制器方法之前将其反序列化为 Widget 对象?
【问题讨论】:
【参考方案1】:感谢 Jeff,这让我走上了正确的道路。 DefaultModelBinder 足够聪明,可以为我做所有的魔法……我的问题出在我的 Widget 类型上。匆忙中,我的类型被定义为:
public class Widget
public int Id;
public string Name;
public decimal Price;
请注意,该类型具有公共字段而不是公共属性。一旦我将它们更改为属性,它就起作用了。下面是正确运行的最终源代码:
Widget.aspx:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Widget.aspx.cs" Inherits="MvcAjaxApp2.Views.Home.Widget" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<script src="../../Scripts/jquery-1.2.6.js" type="text/javascript"></script>
<script type="text/javascript">
function SaveWidget()
var formData = $("#Form1").serializeArray();
$.post("/Home/SaveWidget",
formData,
function(data)
alert(data.Result);
, "json");
</script>
<form id="Form1">
<input type="hidden" name="widget.Id" value="1" />
<input type="text" name="widget.Name" value="my widget" />
<input type="text" name="widget.Price" value="5.43" />
<input type="button" value="Save" onclick="SaveWidget()" />
</form>
</asp:Content>
HomeController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
namespace MvcAjaxApp2.Controllers
[HandleError]
public class HomeController : Controller
public ActionResult Index()
ViewData["Title"] = "Home Page";
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
public ActionResult About()
ViewData["Title"] = "About Page";
return View();
public ActionResult Widget()
ViewData["Title"] = "Widget";
return View();
public JsonResult SaveWidget(Widget widget)
// Save the Widget
return Json(new Result = String.Format("Saved widget: '0' for $1", widget.Name, widget.Price) );
public class Widget
public int Id get; set;
public string Name get; set;
public decimal Price get; set;
【讨论】:
太棒了,很高兴你把它修好了。并感谢您发布您如何修复它,这将在未来对其他人有很大帮助! 公共字段是 .NET 中的恶魔。他们打破了一切。我告诉你的一切! @MrBoJangles - 字段是的问题,解决方案是将它们更改为属性。 我在我的项目中使用了这种格式。它从来没有在$.post()
中运行回调函数,我只是在其中添加了一个通用的alert('Successful');
,不知道为什么没有,但它确实发布了我的数据,我很高兴,所以+1。不知道为什么我的简单$('#Form1').submit()
不起作用,当我有method=post
和action
中的控制器/更新时。
实际上,我发现如果我在回调结束时去掉, "json"
,警报就会起作用。仅供参考。【参考方案2】:
注意(在MrDustpan的解决方案中)MVC Action方法中的参数name widget必须与中使用的前缀匹配>name ASPX 文件中的属性。
如果不是这种情况,那么 Action 方法将始终接收 null 对象。
<input type="text" name="widget.Text" value="Hello" /> - OK
<input type="text" name="mywidget.Text" value="Hello" /> - FAILS
【讨论】:
优秀的一点,很容易被忽视。似乎也区分大小写。【参考方案3】:Phil Haack 有 a good blog post 关于模型绑定可能会有所帮助。不是 100% 您在这里谈论的内容,但我认为这可能会让您对 DefaultModelBinder 有更好的整体了解。
【讨论】:
【参考方案4】:您要做的是以与后端对象相同的方式构建 javascript 表单对象:
Id : "id", Name : "name", Price : 1.0
然后使用toJSON插件将其转换成上面的字符串。您将此字符串发送到后端并使用 JayRock 库之类的东西将其转换为新的 Widget 对象。
【讨论】:
以上是关于如何使用 json 将复杂类型传递给 ASP.NET MVC 控制器的主要内容,如果未能解决你的问题,请参考以下文章
Swift:如何将可编码类型作为函数输入传递给编码或解码 json