我正在尝试使用 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.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 在 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/