发布JSON数据到ASP.NET MVC [英] Posting JSON Data to ASP.NET MVC

查看:116
本文介绍了发布JSON数据到ASP.NET MVC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

林试图获得的订单项的列表使用JSON网页,然后将被操纵和使用相同的JSON结构到达发送回服务器通过Ajax请求(除了有过一个字段值改变)。

从服务器接收数据很容易,操控更加得心应手!但发送的JSON数据返回到服务器保存......自杀的时间!请能有人帮助!

Javascript的

  VAR lineItems的;

//从服务器数据
$阿贾克斯({
    网址:/控制器/的GetData /',
    成功:功能(数据){
        lineItems的=数据;
    }
});

// POST数据到服务器
$阿贾克斯({
    网址:/控制器/保存数据/',
    数据:{来电:lineItems的}
});
 

C# - 对象

 公共类的LineItem {
    公共字符串参考;
    公众诠释数量;
    公共小数金额;
}
 

C# - 控制器

 公共JsonResult的GetData()
{
    IEnumerable的<的LineItem> lineItems的= ...; //一大堆的线项目
    返回JSON(lineItems的);
}

公共JsonResult保存数据(IEnumerable的<的LineItem>进入){
    的foreach(传入的LineItem项){
        //保存一些东西
    }
    返回JSON(新{成功= TRUE,消息=一些信息});
}
 

在数据到达服务器序列化后的数据。自动化模型绑定尝试绑定的IEnumerable<的LineItem>来电和令人惊讶的获得所产生的的IEnumerable 了LineItem 的正确的号码 - 它只是不用数据填充。

解决方案:

使用的答案从许多来源,主要是 djch 上的另一个计算器后和 BeRecursive 下面,我解决我的问题使用两种主要的方法。

服务器端

在解串器下面要求引用 System.Runtime.Serialization 使用System.Runtime.Serialization.Json

 私人牛逼Deserialise< T>(JSON字符串)
    {
        使用(VAR毫秒=新的MemoryStream(Encoding.Uni code.GetBytes(JSON)))
        {
            VAR串行器=新DataContractJsonSerializer(typeof运算(T));
            返程(T)serialiser.ReadObject(MS);
        }
    }

    公共无效动作(INT ID,字符串项){
        IEnumerable的<的LineItem> lineItems的= Deserialise< IEnumerable的<的LineItem>>(项目);
        //做任何需要做的事情 - 创建,修改,删除等。
    }
 

客户端

它使用json.org的字符串化的方法,可以通过这种关系是不<一个href="https://github.com/douglascrockford/JSON-js/blob/master/json2.js">https://github.com/douglascrockford/JSON-js/blob/master/json2.js (这是精缩时2.5KB)

  $。阿贾克斯({
            键入:POST,
            网址:/控制器/动作,
            数据:{项目:JSON.stringify(lineItems的),ID:documentId}
        });
 

解决方案

看看菲尔哈克的帖子在<一个href="http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx">model结合JSON数据。的问题是,默认模型粘合剂不能正确序列的JSON。你需要某种ValueProvider,或者你可以写一个自定义的模型绑定:

 使用System.IO;
使用System.Web.Script.Serialization;

公共类JsonModelBinder:DefaultModelBinder {
        公众覆盖对象BindModel(ControllerContext controllerContext,ModelBindingContext的BindingContext){
            如果(!IsJSONRequest(controllerContext)){
                返回base.BindModel(controllerContext,BindingContext中);
            }

            //获取一个已经发布的JSON数据
            VAR请求= controllerContext.HttpContext.Request;
            //在某些设置有一些已经读取输入流,如果内容类型=应用/ JSON的,因此力求开始时
            request.InputStream.Seek(0,SeekOrigin.Begin);
            VAR jsonStringData =新的StreamReader(request.InputStream).ReadToEnd();

            //使用内置的序列化器做的工作对我们来说
            返回新JavaScriptSerializer()
                .Deserialize(jsonStringData,bindingContext.ModelMetadata.ModelType);

            //  - 需要.NET4
            //如果你想使用.NET4版本这一点,改变目标框架,并取消下面的行
            //并注释掉上面的return语句
            //返回新JavaScriptSerializer()反序列化(jsonStringData,bindingContext.ModelMetadata.ModelType)。
        }

        私有静态布尔IsJSONRequest(ControllerContext controllerContext){
            VAR的contentType = controllerContext.HttpContext.Request.ContentType;
            返回contentType.Contains(应用/ JSON);
        }
    }

公共静态类JavaScriptSerializerExt {
        公共静态对象的反序列化(这JavaScriptSerializer串,串输入型OBJTYPE){
            。VAR deserializerMethod = serializer.GetType()GetMethod的(反序列化,BindingFlags.NonPublic可| BindingFlags.Static);

            //内部静态方法来为我们做的工作
            //反序列化(这一点,输入,空,this.RecursionLimit);

            返回deserializerMethod.Invoke(串行器,
                新对象[] {串行输入,OBJTYPE,serializer.RecursionLimit});
        }
    }
 

和告诉MVC使用它在Global.asax文件:

  ModelBinders.Binders.DefaultBinder =新JsonModelBinder();
 

此外,该code利用的内容类型=应用/ JSON的,所以一定要设置在jQuery的像这样:

  $。阿贾克斯({
    数据类型:JSON,
    的contentType:应用/ JSON
    键入:POST,
    网址:/控制器/动作,
    数据:{项目:JSON.stringify(lineItems的),ID:documentId}
});
 

Im trying to get a list of line items to a webpage using JSON, which will then be manipulated and sent back to the server by ajax request using the same JSON structure that arrived (except having had a field values changed).

Receiving data from the server is easy, manipulation even easier! but sending that JSON data back to the server for saving... suicide time! PLEASE can someone help!

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# - Objects

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

The data arrives at the server as serialized post data. The automated model binder tries to bind IEnumerable<LineItem> incoming and surprisingly gets the resulting IEnumerable has the correct number of LineItems - it just doesnt populate them with data.

SOLUTION

Using answers from a number of sources, primarily djch on another stackoverflow post and BeRecursive below, I solved my problem using two main methods.

Server Side

The deserialiser below requires reference to System.Runtime.Serialization and using 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.
    }

Client Side

It uses json.org's stringify method, available in this dependecy https://github.com/douglascrockford/JSON-js/blob/master/json2.js (which is 2.5kb when minified)

        $.ajax({
            type: 'POST',
            url: '/Controller/Action',
            data: { 'items': JSON.stringify(lineItems), 'id': documentId }
        });

解决方案

Take a look at Phil Haack's post on model binding JSON data. The problem is that the default model binder doesn't serialize JSON properly. You need some sort of ValueProvider OR you could write a custom model binder:

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

And tell MVC to use it in your Global.asax file:

ModelBinders.Binders.DefaultBinder = new JsonModelBinder();

Also, this code makes use of the content type = 'application/json' so make sure you set that in jquery like so:

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

这篇关于发布JSON数据到ASP.NET MVC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆