標籤:mvc還原序列化 mvc全域還原序列化 valueproviderfactori global 還原序列化 newtonsoft.json
mvc中預設使用的json返回序列化工具是JsonValueProviderFactory,JsonValueProviderFactory繼承自ValueProviderFactory抽象類別。JsonValueProviderFactory使用的序列化類別庫是System.Web.Script.Serialization。現在我們來寫一個自己的方序列話工具,採用的是Newtonsoft.Json序列化和還原序列化工具。
JsonValueProviderFactory代碼具體如下:
using System;using System.Collections;using System.Collections.Generic;using System.Dynamic;using System.Globalization;using System.IO;using System.Web.Mvc;using Newtonsoft.Json;using Newtonsoft.Json.Converters;namespace Aft.Build.MvcWeb.Common{ public class JsonNetValueProviderFactory : ValueProviderFactory { public override IValueProvider GetValueProvider(ControllerContext controllerContext) { // first make sure we have a valid context if (controllerContext == null) throw new ArgumentNullException("controllerContext"); // now make sure we are dealing with a json request if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) return null; // get a generic stream reader (get reader for the http stream) var streamReader = new StreamReader(controllerContext.HttpContext.Request.InputStream); // convert stream reader to a JSON Text Reader var jsonReader = new JsonTextReader(streamReader); // tell JSON to read if (!jsonReader.Read()) return null; // make a new Json serializer var jsonSerializer = new JsonSerializer(); // add the dyamic object converter to our serializer jsonSerializer.Converters.Add(new ExpandoObjectConverter()); // use JSON.NET to deserialize object to a dynamic (expando) object Object jsonObject; // if we start with a "[", treat this as an array if (jsonReader.TokenType == JsonToken.StartArray) jsonObject = jsonSerializer.Deserialize<List<ExpandoObject>>(jsonReader); else jsonObject = jsonSerializer.Deserialize<ExpandoObject>(jsonReader); // create a backing store to hold all properties for this deserialization var backingStore = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); // add all properties to this backing store AddToBackingStore(backingStore, String.Empty, jsonObject); // return the object in a dictionary value provider so the MVC understands it return new DictionaryValueProvider<object>(backingStore, CultureInfo.CurrentCulture); } private static void AddToBackingStore(Dictionary<string, object> backingStore, string prefix, object value) { var d = value as IDictionary<string, object>; if (d != null) { foreach (var entry in d) { AddToBackingStore(backingStore, MakePropertyKey(prefix, entry.Key), entry.Value); } return; } var l = value as IList; if (l != null) { for (int i = 0; i < l.Count; i++) { AddToBackingStore(backingStore, MakeArrayKey(prefix, i), l[i]); } return; } // primitive backingStore[prefix] = value; } private static string MakeArrayKey(string prefix, int index) { return prefix + "[" + index.ToString(CultureInfo.InvariantCulture) + "]"; } private static string MakePropertyKey(string prefix, string propertyName) { return (String.IsNullOrEmpty(prefix)) ? propertyName : prefix + "." + propertyName; } }}
然後把JsonValueProviderFactory註冊給全域json資料還原序列化使用:
在Global.asax檔案Application_Start方法中添加如下兩行代碼:
ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault()); ValueProviderFactories.Factories.Add(new JsonNetValueProviderFactory());
第一句是移除原來的JsonValueProviderFactory還原序列化,第二句是添加自己的還原序列化工具。
總結及注意事項:
1.mvc用戶端資料到伺服器段的資料類型轉換都是在通過ValueProviderFactories來註冊的。
2.切記mvc中通過ajax來傳到伺服器段的資料報文頭記得一定要Content-Type:application/json,不然不會使用我們上面自己的JsonNetValueProviderFactory還原序列化工具