You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

向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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:46:20