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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/267707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 08:51:32  来源:igfitidea点击:

How to pass complex type using json to ASP.NET MVC controller

asp.netjqueryasp.net-mvcjson

提问by MrDustpan

I have a View that allows a user to enter/edit data for a new Widget. I'd like to form up that data into a json object and send it to my controller via AJAX so I can do the validation on the server without a postback.

我有一个视图,允许用户输入/编辑新小部件的数据。我想将该数据组成一个 json 对象并通过 AJAX 将其发送到我的控制器,以便我可以在服务器上进行验证而无需回发。

I've got it all working, except I can't figure out how to pass the data so my controller method can accept a complex Widget type instead of individual parameters for each property.

我已经完成了所有工作,只是我不知道如何传递数据,以便我的控制器方法可以接受复杂的 Widget 类型,而不是每个属性的单独参数。

So, if this is my object:

所以,如果这是我的对象:

public class Widget
{
   public int Id { get; set; }
   public string Name { get; set; }
   public decimal Price { get; set; }
}

I'd like my controller method to look something like this:

我希望我的控制器方法看起来像这样:

public JsonResult Save(Widget widget)
{
   ...
}

Currently, my jQuery looks like this:

目前,我的 jQuery 看起来像这样:

var formData = $("#Form1").serializeArray();

$.post("/Widget/Save",
   formData,
   function(result){}, "json");

My form (Form1) has an input field for each property on the Widget (Id, Name, Price). This works great, but it ultimately passes each property of the Widget as a separate parameter to my controller method.

我的表单 (Form1) 为小部件上的每个属性(Id、Name、Price)都有一个输入字段。这很好用,但它最终将 Widget 的每个属性作为单独的参数传递给我的控制器方法。

Is there a way I could "intercept" the data, maybe using an ActionFilterAttribute, and deserialize it to a Widget object before my controller method gets called?

有没有办法可以“拦截”数据,也许使用 ActionFilterAttribute,并在调用我的控制器方法之前将其反序列化为 Widget 对象?

采纳答案by MrDustpan

Thanks Jeff, that got me on the right path. The DefaultModelBinder is smart enough to do all the magic for me...my problem was in my Widget type. In my haste, my type was defined as:

谢谢杰夫,这让我走上了正确的道路。DefaultModelBinder 足够聪明,可以为我做所有的魔法……我的问题出在我的 Widget 类型上。在我匆忙中,我的类型被定义为:

public class Widget
{
   public int Id;
   public string Name;
   public decimal Price;
}

Notice that the type has public fields instead of public properties. Once I changed those to properties, it worked. Here's the final source code that works correctly:

请注意,该类型具有公共字段而不是公共属性。一旦我将它们更改为属性,它就起作用了。这是最终可以正常工作的源代码:

Widget.aspx:

小部件.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:

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 ", widget.Name, widget.Price) });
        }
    }
    public class Widget
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
}

回答by Simon Sanderson

Note that (in MrDustpan'ssolution) the parameter namewidgetin the MVC Action method must match with the prefix used in the nameattribute in the ASPX file.

请注意(在MrDustpan 的解决方案中)MVC Action 方法中的参数名称小部件必须与ASPX 文件中名称属性中使用的前缀匹配。

If this is not the case then the Action method will always receive a nullobject.

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

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

回答by Jeff Sheldon

Phil Haackhas a good blog postabout model binding that might be helpful. Not 100% what you're talking about here, but I think it might give you a better overall understand about the DefaultModelBinder.

Phil Haack一篇关于模型绑定的好博文,可能会有所帮助。不是 100% 你在这里谈论的是什么,但我认为它可能会让你对 DefaultModelBinder 有一个更好的整体了解。

回答by Sugendran

What you want to do is structure your javascript form object in the same way your backend object is structured:

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

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

Then use the toJSON plugin to convert it into the above string. You send this string to your backend and use something like the JayRock libraries to convert it to a new Widget object.

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