我试图使用JSON获取网页的订单项列表,然后将使用到达的相同JSON结构(通过更改字段值除外)通过ajax请求对其进行处理并发送回服务器。
从服务器接收数据很容易,甚至更容易操作!但是将JSON数据发送回服务器以节省…自杀时间!请有人帮忙!
Java脚本
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-它只是不使用数据填充它们。
IEnumerable<LineItem> incoming
IEnumerable
LineItems
解
我使用了很多资料来源的答案,主要是djch在另一个stackoverflow帖子及其BeRecursive下面,使用两种主要方法解决了我的问题。
djch
BeRecursive
服务器端
以下解串器需要参考System.Runtime.Serialization和using System.Runtime.Serialization.Json
System.Runtime.Serialization
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. }
客户端
它使用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 } });