向ASP.NET MVC控制器传递多图JSON数据失败问题求助
解决ASP.NET MVC多图AJAX上传JSON数据过大的问题
我之前碰到过完全一致的场景:在ASP.NET MVC Web应用里,表单包含标题、描述这类文本数据,还有需要前端压缩的图片。把所有数据封装成JSON通过AJAX发去服务器时,单图上传一切正常,但多图上传就直接触发错误回调,调试发现前端数据没问题,后来排查出是JSON数据长度超限和请求内容长度限制导致的问题,最终通过以下两步解决:
1. 自定义JsonValueProviderFactory替换默认工厂
默认的JsonValueProviderFactory对JSON数据长度有严格限制,我们需要自定义一个来支持更大的JSON payload:
public class LargeJsonValueProviderFactory : JsonValueProviderFactory { private static void AddToBackingStore(EntryLimitedDictionary backingStore, string prefix, object value) { var dictionary = value as IDictionary<string, object>; if (dictionary != null) { foreach (var entry in dictionary) { AddToBackingStore(backingStore, MakePropertyKey(prefix, entry.Key), entry.Value); } return; } var list = value as IList; if (list != null) { for (int i = 0; i < list.Count; i++) { AddToBackingStore(backingStore, MakeArrayKey(prefix, i), list[i]); } return; } // 处理基础类型数据 backingStore.Add(prefix, value); } private static object GetDeserializedObject(ControllerContext controllerContext) { if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) { // 非JSON请求直接返回null return null; } var reader = new StreamReader(controllerContext.HttpContext.Request.InputStream); var bodyText = reader.ReadToEnd(); if (string.IsNullOrEmpty(bodyText)) { // 无JSON数据返回null return null; } var serializer = new JavaScriptSerializer(); serializer.MaxJsonLength = int.MaxValue; // 解除JSON长度限制 return serializer.DeserializeObject(bodyText); } public override IValueProvider GetValueProvider(ControllerContext controllerContext) { if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } var jsonData = GetDeserializedObject(controllerContext); if (jsonData == null) { return null; } var backingStore = new EntryLimitedDictionary(); AddToBackingStore(backingStore, string.Empty, jsonData); return new DictionaryValueProvider<object>(backingStore, CultureInfo.CurrentCulture); } 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; } private class EntryLimitedDictionary : Dictionary<string, object> { // 可根据业务调整,这里设置为最大条目数 private const int _maxEntries = int.MaxValue; public new void Add(string key, object value) { if (Count >= _maxEntries) { throw new InvalidOperationException("JSON payload体积过大"); } base.Add(key, value); } } }
然后在Global.asax.cs的Application_Start方法中替换默认工厂:
protected void Application_Start() { // 移除默认的JsonValueProviderFactory ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault()); // 添加自定义的大体积JSON支持工厂 ValueProviderFactories.Factories.Add(new LargeJsonValueProviderFactory()); // 其他项目初始化代码 AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); }
2. 修改Web.config配置请求内容长度限制
除了JSON长度限制,还需要同时调整ASP.NET运行时和IIS的请求内容大小限制,在Web.config中添加以下配置:
<system.web> <!-- maxRequestLength单位为KB,这里设置为100MB --> <httpRuntime targetFramework="你的.NET版本" maxRequestLength="102400" /> </system.web> <system.webServer> <security> <requestFiltering> <!-- maxAllowedContentLength单位为字节,这里设置为100MB --> <requestLimits maxAllowedContentLength="104857600" /> </requestFiltering> </security> </system.webServer>
额外说明
- 单图正常多图失败的核心原因:单图压缩后的base64数据量小,没触发默认长度阈值;多图时数据总和超过了限制,导致请求被拦截或JSON反序列化失败。
- 自定义工厂的核心是解除
JavaScriptSerializer的MaxJsonLength限制,同时调整字典条目数上限,确保能处理大体积JSON。 - Web.config的两个配置缺一不可,分别对应ASP.NET运行时和IIS的请求大小管控逻辑。
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

