ASP.NET MVC 如何将 JSON 对象作为参数从视图传递到控制器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/560575/
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-09-03 17:11:25  来源:igfitidea点击:

ASP.NET MVC How to pass JSON object from View to Controller as Parameter

asp.net-mvcjson

提问by Rosstified

I have a complex JSON object which is sent to the View without any issues (as shown below) but I cannot work out how Serialize this data back to a .NET object when it is passed back to the controller through an AJAX call. Details of the various parts are below.

我有一个复杂的 JSON 对象,它可以毫无问题地发送到视图(如下所示),但是当它通过 AJAX 调用传递回控制器时,我无法弄清楚如何将此数据序列化回 .NET 对象。各部分的详细信息如下。

   var ObjectA = {
        "Name": 1,
        "Starting": new Date(1221644506800),

        "Timeline": [
            {
                "StartTime": new Date(1221644506800),
                "GoesFor": 200

            }
            ,
            {
                "StartTime": new Date(1221644506800),
                "GoesFor": 100

            }

        ]
    };

I am not sure how this object can be passed to a Controller Method, I have this method below where the Timelines object mirrors the above JS object using Properties.

我不确定如何将此对象传递给控制器​​方法,我在下面使用了此方法,其中 Timelines 对象使用 Properties 镜像了上述 JS 对象。

public JsonResult Save(Timelines person)

The jQuery I am using is:

我正在使用的 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();
            }
        });

I have seen this question which is similar, but not quite the same as I am not using a forms to manipulate the data. How to pass complex type using json to ASP.NET MVC controller

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

I have also seen references to using a 'JsonFilter' to manually deserialize the JSON, but was wondering if there is a way to do it nativly though ASP.NET MVC? Or what are the best practices for passing data in this way?

我还看到了使用“JsonFilter”手动反序列化 JSON 的参考资料,但想知道是否有办法通过 ASP.NET MVC 原生地做到这一点?或者以这种方式传递数据的最佳实践是什么?

采纳答案by ChadT

Edit:

编辑:

This method should no longer be needed with the arrival of MVC 3, as it will be handled automatically - http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx

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



You can use this 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;
        }

    }
}

You can then apply it to your controller methods like so:

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

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

So basically, if the content type of the post is "application/json" this will spring into action and will map the values to the object of type you specify.

所以基本上,如果帖子的内容类型是“application/json”,这将生效并将值映射到您指定的类型的对象。

回答by Craig Stuntz

You say "I am not using a forms to manipulate the data." But you are doing a POST. Therefore, you are, in fact, using a form, even if it's empty.

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

$.ajax's dataTypetells jQuery what type the server will return, not what you are passing. POST can only pass a form. jQuery will convert data to key/value pairsand pass it as a query string. From the docs:

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

Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests. See processData option to prevent this automatic processing. Object must be Key/Value pairs. If value is an Array, jQuery serializes multiple values with same key i.e. {foo:["bar1", "bar2"]} becomes '&foo=bar1&foo=bar2'.

要发送到服务器的数据。如果不是字符串,则将其转换为查询字符串。它附加到 GET 请求的 url。请参阅 processData 选项以防止此自动处理。对象必须是键/值对。如果 value 是一个数组,jQuery 将序列化多个具有相同键的值,即 {foo:["bar1", "bar2"]} 变为 '&foo=bar1&foo=bar2'。

Therefore:

所以:

  1. You aren't passing JSON to the server. You're passing JSON to jQuery.
  2. Model binding happens in the same way it happens in any other case.
  1. 您没有将 JSON 传递给服务器。您正在将 JSON 传递给 jQuery。
  2. 模型绑定的发生方式与在任何其他情况下发生的方式相同。

回答by Robert Koritnik

A different take with a simple jQuery plugin

一个简单的 jQuery 插件的不同之处

Even though answers to this question are long overdue, but I'm still posting a nice solution that I came with some time ago and makes it really simple to send complex JSON to Asp.net MVCcontroller actions so they are model bound to whatever strong type parameters.

尽管这个问题的答案早就应该了,但我仍然发布了一个很好的解决方案,我前一段时间来了,它使得将复杂的 JSON 发送到 Asp.net MVC控制器操作变得非常简单,因此它们被模型绑定到任何强大的类型参数。

This plugin supports datesjust as well, so they get converted to their DateTimecounterpart without a problem.

这个插件也支持日期,因此它们可以DateTime毫无问题地转换为对应的日期。

You can find all the details in my blog postwhere I examine the problem and provide code necessary to accomplish this.

您可以在我的博客文章中找到所有详细信息,在其中检查了问题并提供了完成此操作所需的代码。

All you have to do is to use this plugin on the client side. An Ajax request would look like this:

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

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

But this is just part of the whole problem. Now we are able to post complex JSON back to server, but since it will be model bound to a complex type that may have validation attributes on properties things may fail at that point. I've got a solution for it as well. My solution takes advantage of jQuery Ajax functionality where results can be successful or erroneous (just as shown in the upper code). So when validation would fail, errorfunction would get called as it's supposed to be.

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

回答by swilliams

There is the JavaScriptSerializerclass you can use too. That will let you deserialize the json to a .NET object. There's a generic Deserialize<T>, though you will need the .NET object to have a similar signature as the javascript one. Additionally there is also a DeserializeObjectmethod that just makes a plain object. You can then use reflection to get at the properties you need.

还有就是JavaScriptSerializer你可以使用过类。这将让您将 json 反序列化为 .NET 对象。有一个通用的Deserialize<T>,但您需要 .NET 对象具有与 javascript 类似的签名。此外,还有一种DeserializeObject方法可以制作简单的object. 然后您可以使用反射来获取您需要的属性。

If your controller takes a FormCollection, and you didn't add anything else to the datathe json should be in form[0]:

如果您的控制器采用FormCollection,并且您没有data向 json 中添加任何其他内容,则应该在form[0]

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

回答by Chev

This answer is a follow up to DaRKoN_'s answer that utilized the object filter:

这个答案是 DaRKoN_ 使用对象过滤器的答案的后续:

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

I was having a problem figuring out how to send multiple parameters to an action method and have one of them be the json object and the other be a plain string. I'm new to MVC and I had just forgotten that I already solved this problem with non-ajaxed views.

我在弄清楚如何将多个参数发送到操作方法并让其中一个是 json 对象而另一个是纯字符串时遇到了问题。我是 MVC 的新手,我刚刚忘记我已经用非 ajaxed 视图解决了这个问题。

What I would do if I needed, say, two different objects on a view. I would create a ViewModel class. So say I needed the person object and the address object, I would do the following:

如果我需要,比如说,视图上有两个不同的对象,我会怎么做。我会创建一个 ViewModel 类。所以说我需要 person 对象和 address 对象,我会做以下事情:

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

Then I would bind the view to SomeViewModel. You can do the same thing with JSON.

然后我会将视图绑定到 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);
}

Then in the view you can use a simple call with JQuery like this:

然后在视图中,您可以像这样对 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;
     }
});

回答by user715852

in response to Dan's comment above:

回应上面丹的评论:

I am using this method to implement the same thing, but for some reason I am getting an exception on the ReadObject method: "Expecting element 'root' from namespace ''.. Encountered 'None' with name '', namespace ''." Any ideas why? – Dan Appleyard Apr 6 '10 at 17:57

我正在使用这个方法来实现同样的事情,但由于某种原因,我在 ReadObject 方法上遇到了一个异常:“Expecting element 'root' from namespace ''.. Encountered 'None' with name '', namespace ''. ” 任何想法为什么?– Dan Appleyard 2010 年 4 月 6 日,17:57

I had the same problem (MVC 3 build 3.0.11209.0), and the post below solved it for me. Basically the json serializer is trying to read a stream which is not at the beginning, so repositioning the stream to 0 'fixed' it...

我遇到了同样的问题(MVC 3 build 3.0.11209.0),下面的帖子为我解决了这个问题。基本上 json 序列化程序试图读取不在开头的流,因此将流重新定位为 0 '固定'它......

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

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