如何使用json将复杂类型传递给ASP.NET MVC控制器

时间:2008-11-06 05:19:38

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

我有一个允许用户输入/编辑新Widget数据的视图。我想将这些数据组成一个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对象?

4 个答案:

答案 0 :(得分:25)

谢谢杰夫,这让我走上了正确的道路。 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; }
    }
}

答案 1 :(得分:6)

请注意(在 MrDustpan的解决方案中)MVC Action方法中的参数 name widget 必须与 ASPX文件中的名称属性。

如果不是这种情况,则Action方法将始终收到 null 对象。

<input type="text" name="widget.Text" value="Hello" /> - OK
<input type="text" name="mywidget.Text" value="Hello" /> - FAILS

答案 2 :(得分:4)

Phil Haacka good blog post关于可能有用的模型绑定。不是100%你在这里谈论的,但我认为这可能会让你更好地了解DefaultModelBinder。

答案 3 :(得分:2)

您要做的是以与后端对象结构相同的方式构建您的javascript表单对象:

{ Id : "id", Name : "name", Price : 1.0 }

然后使用toJSON插件将其转换为上面的字符串。您将此字符串发送到后端并使用类似JayRock库的内容将其转换为新的Widget对象。