c# - 将 JSON 数据发布到 ASP.NET MVC

标签 c# jquery asp.net-mvc ajax json

我正在尝试使用 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# - Controller

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" });
}

数据作为序列化的 post 数据到达服务器。自动模型绑定(bind)器尝试绑定(bind) 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 在 model binding JSON data 上的帖子.问题是默认模型绑定(bind)器没有正确序列化 JSON。您需要某种 ValueProvider 或者您可以编写自定义模型绑定(bind)器:

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 }
});

关于c# - 将 JSON 数据发布到 ASP.NET MVC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4164114/

相关文章:

c# - 图像浏览器在 Razor View 的 CkEditor 中不工作

javascript - 如何将变量从当前窗口传递到另一个窗口

c# - 用于删除 ID 不等于 ID 列表的所有对象的 LINQ 查询现在可以正常工作

c# - Backgroundworker 不会报告进度

c# - 自定义配置部分 : CallbackValidator called with empty string

c# - Xamarin - 尝试共享时找不到文件

c# - lambda 语法中的 linq 类型声明

javascript - 我们如何通过使用来自另一个 div 的链接使 DIV 可点击

javascript - 表格行中的 onClick 在 JavaScript/jQuery 中不起作用

asp.net-mvc - 我可以避免这种永久重定向来修复或添加 slug 吗?