如何将JSON数据发布到ASP.NETMVC?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (24)

我试图使用JSON获取行项目列表到网页,然后通过使用与到达相同的JSON结构(除了字段值已更改除外)通过ajax请求被操纵并发送回服务器。

从服务器接收数据很容易,操作更简单!但将该JSON数据发送回服务器以保存......自杀时间!请有人可以帮忙!

使用Javascript

var lineitems;

// get data from server
$.ajax({
    url: '/Controller/GetData/',
    success: function(data){
        lineitems = data;
    }
});

// post data to server
$.ajax({
    url: '/Controller/SaveData/',
    data: { incoming: lineitems }
});

C# - 对象

public class LineItem{
    public string reference;
    public int quantity;
    public decimal amount;
}

C# - 控制器

public JsonResult GetData()
{
    IEnumerable<LineItem> lineItems = ... ; // a whole bunch of line items
    return Json(lineItems);
}

public JsonResult SaveData(IEnumerable<LineItem> incoming){
    foreach(LineItem item in incoming){
        // save some stuff
    }
    return Json(new { success = true, message = "Some message" });
}

数据以序列化后的数据到达服务器。自动化的模型绑定器试图绑定IEnumerable<LineItem> incoming并且令人惊讶地得到的结果IEnumerable具有正确的数量LineItems- 它只是没有用数据填充它们。

使用来自多个来源的答案,主要djch在另一个stackoverflow帖子和BeRecursive下面,我使用两种主要方法解决了我的问题。

服务器端

下面的反序列化器需要参考System.Runtime.Serializationusing System.Runtime.Serialization.Json

    private T Deserialise<T>(string json)
    {
        using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
        {
            var serialiser = new DataContractJsonSerializer(typeof(T));
            return (T)serialiser.ReadObject(ms);
        }
    }

    public void Action(int id, string items){
        IEnumerable<LineItem> lineitems = Deserialise<IEnumerable<LineItem>>(items);
        // do whatever needs to be done - create, update, delete etc.
    }

客户端

它使用json.org的stringify方法,可用于此依赖性https://github.com/douglascrockford/JSON-js/blob/master/json2.js(缩小时为2.5kb)

        $.ajax({
            type: 'POST',
            url: '/Controller/Action',
            data: { 'items': JSON.stringify(lineItems), 'id': documentId }
        });
提问于
用户回答回答于

看看Phil Haack的模型绑定JSON数据的帖子。问题是默认的模型联编程序不能正确序列化JSON。需要某种ValueProvider,或者可以编写一个自定义模型绑定器:

using System.IO;
using System.Web.Script.Serialization;

public class JsonModelBinder : DefaultModelBinder {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
            if(!IsJSONRequest(controllerContext)) {
                return base.BindModel(controllerContext, bindingContext);
            }

            // Get the JSON data that's been posted
            var request = controllerContext.HttpContext.Request;
            //in some setups there is something that already reads the input stream if content type = 'application/json', so seek to the begining
            request.InputStream.Seek(0, SeekOrigin.Begin);
            var jsonStringData = new StreamReader(request.InputStream).ReadToEnd();

            // Use the built-in serializer to do the work for us
            return new JavaScriptSerializer()
                .Deserialize(jsonStringData, bindingContext.ModelMetadata.ModelType);

            // -- REQUIRES .NET4
            // If you want to use the .NET4 version of this, change the target framework and uncomment the line below
            // and comment out the above return statement
            //return new JavaScriptSerializer().Deserialize(jsonStringData, bindingContext.ModelMetadata.ModelType);
        }

        private static bool IsJSONRequest(ControllerContext controllerContext) {
            var contentType = controllerContext.HttpContext.Request.ContentType;
            return contentType.Contains("application/json");
        }
    }

public static class JavaScriptSerializerExt {
        public static object Deserialize(this JavaScriptSerializer serializer, string input, Type objType) {
            var deserializerMethod = serializer.GetType().GetMethod("Deserialize", BindingFlags.NonPublic | BindingFlags.Static);

            // internal static method to do the work for us
            //Deserialize(this, input, null, this.RecursionLimit);

            return deserializerMethod.Invoke(serializer,
                new object[] { serializer, input, objType, serializer.RecursionLimit });
        }
    }

并告诉MVC在你的Global.asax文件中使用它:

ModelBinders.Binders.DefaultBinder = new JsonModelBinder();

此外,这段代码使用内容类型='application / json',所以确保你在jquery中设置如下所示:

$.ajax({
    dataType: "json",
    contentType: "application/json",            
    type: 'POST',
    url: '/Controller/Action',
    data: { 'items': JSON.stringify(lineItems), 'id': documentId }
});
用户回答回答于

这是最简单的方法

我强烈建议阅读这篇直接解决问题的博文

Phil Haack指出,使用自定义模型粘合剂并不是真正的明智之举(他的博客文章也链接在上面的博客文章中)。

基本上你有三个选择:

  1. 编写JsonValueProviderFactory并使用客户端库,json2.js以便直接与JSON进行通信。
  2. 编写一个JQueryValueProviderFactory能够理解在$.ajax或中发生的jQuery JSON对象转换
  3. 使用在博客文章概述了非常简单和快捷的jQuery插件,即准备任何JSON对象(甚至阵列将被绑定到IList<T>日期,将在服务器端的正确分析DateTime,将通过Asp.net MVC默认情况下可以理解实例)模型活页夹。

其中最后一个是最简单的,不会干扰Asp.net MVC内部工作,从而降低可能的bug表面。使用博客文章中概述的技术将正确的数据绑定强类型操作参数并验证它们。所以这基本上是双赢的局面。

扫码关注云+社区