透過 $http.post 呼叫 action 並帶入參數,但參數值較大(例如檔案內容),會遇到如下訊息
使用 JSON JavaScriptSerializer 序列化或還原序列化期間發生錯誤。字串的長度超過在 maxJsonLength 屬性上設定的值
好處
1. 效能較快
2. action 輸入跟輸出不會有長度限制
作法
1. 建立 JsonNetValueProviderFactory
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)
StreamReader streamReader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
// convert stream reader to a JSON Text Reader
JsonTextReader JSONReader = new JsonTextReader(streamReader);
// tell JSON to read
if (!JSONReader.Read())
return null;
// make a new Json serializer
JsonSerializer JSONSerializer = new JsonSerializer() { DateTimeZoneHandling= DateTimeZoneHandling.Local };
// 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
- >(JSONReader);
else
JSONObject = JSONSerializer.Deserialize
// create a backing store to hold all properties for this deserialization
Dictionary
// 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
{
IDictionary
if (d != null)
{
foreach (KeyValuePair
{
AddToBackingStore(backingStore, MakePropertyKey(prefix, entry.Key), entry.Value);
}
return;
}
IList 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;
}
}
2. Global.asax.cs Application_Start() 增加如下內容
ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>
ValueProviderFactories.Factories.Add(new JsonNetValueProviderFactory());
3. 建立 JsonNetResult.cs
public class JsonNetResult : JsonResult
{
public JsonSerializerSettings SerializerSettings { get; set; }
public Formatting Formatting { get; set; }
public JsonNetResult()
{
SerializerSettings = new JsonSerializerSettings();
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
HttpResponseBase response = context.HttpContext.Response;
response.ContentType =
!string.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
if (ContentEncoding != null)
response.ContentEncoding = ContentEncoding;
if (Data != null)
{
JsonTextWriter writer = new JsonTextWriter(response.Output)
{
Formatting = Formatting,
};
JsonSerializer serializer = JsonSerializer.Create(SerializerSettings);
serializer.Serialize(writer, Data); writer.Flush();
}
}
}
4. 建立 JsonNetController
public class JsonNetController : Controller
{
protected override JsonResult Json(object data, string contentType=null,
System.Text.Encoding contentEncoding=null, JsonRequestBehavior behavior= JsonRequestBehavior.AllowGet)
{
if (behavior == JsonRequestBehavior.DenyGet
&& string.Equals(this.Request.HttpMethod, "GET",
StringComparison.OrdinalIgnoreCase))
//Call JsonResult to throw the same exception as JsonResult
return new JsonResult();
return new JsonNetResult()
{
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding,
SerializerSettings= new Newtonsoft.Json.JsonSerializerSettings() { DateTimeZoneHandling= Newtonsoft.Json.DateTimeZoneHandling.Local }
};}
}
並讓繼承Controller 的改為繼承JsonNetController
說明
1. 輸出 json 方式不變,但會改用 json.net 處理
return Json(list);
2. 輸入和輸出預設會考慮本地時區,不需要刻意設定
3. 若還是出現錯誤訊息 "超出最大的要求長度 ",則修改 web.config 的 httpRuntime,加入 maxRequestLength="2147483647"