发布JSON数据到ASP.NET MVC [英] Posting JSON Data to 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屋!