gpt4 book ai didi

c# - 反序列化大型 json 对象的 JsonMaxLength 异常

转载 作者:IT老高 更新时间:2023-10-28 12:51:39 26 4
gpt4 key购买 nike

简介:

Web 应用程序,ASP.NET MVC 3,一个 Controller 操作,它接受具有(可能)大字段的 POCO 模型类的实例。

模型类:

public class View
{
[Required]
[RegularExpression(...)]
public object name { get; set; }
public object details { get; set; }
public object content { get; set; } // the problem field
}

Controller Action :

[ActionName(...)]
[Authorize(...)]
[HttpPost]
public ActionResult CreateView(View view)
{
if (!ModelState.IsValid) { return /*some ActionResult here*/;}
... //do other stuff, create object in db etc. return valid result
}

问题:

一个 Action 应该能够接受大型 JSON 对象(在单个请求中至少达到数百兆字节,这不是开玩笑)。默认情况下,我遇到了几个限制,例如 httpRuntime maxRequestLength等等 - 除了 MaxJsonLengh 之外都已解决 - 这意味着 JSON 的默认 ValueProviderFactory 无法处理此类对象。

试过了:

设置

  <system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="2147483647"/>
</webServices>
</scripting>
</system.web.extensions>
  • 没有帮助。

创建我自己的自定义 ValueProviderFactory,如@Darin 的回答中所述:

JsonValueProviderFactory throws "request too large"

  • 也失败了,因为我无法使用 JSON.Net(由于非技术原因)。我试图自己在这里实现正确的反序列化,但显然它有点超出我的知识(还)。我能够将我的 JSON 字符串反序列化为 Dictionary<String,Object>在这里,但这不是我想要的 - 我想将它反序列化为我可爱的 ​​POCO 对象并将它们用作操作的输入参数。

那么问题来了:

  1. 有谁知道在不实现通用自定义 ValueProviderFactory 的情况下克服该问题的更好方法?
  2. 是否可以指定我想使用我的自定义 ValueProviderFactory 的特定 Controller 和操作?如果我事先知道该操作,我将能够将 JSON 反序列化为 POCO,而无需在 ValueProviderFactory 中进行大量编码...
  3. 我也在考虑针对该特定问题实现自定义 ActionFilter,但我认为这有点难看。

谁能提出一个好的解决方案?

最佳答案

内置的 JsonValueProviderFactory 忽略了 <jsonSerialization maxJsonLength="50000000"/>环境。因此,您可以使用内置实现来编写自定义工厂:

public sealed class MyJsonValueProviderFactory : ValueProviderFactory
{
private static void AddToBackingStore(Dictionary<string, object> backingStore, string prefix, object value)
{
IDictionary<string, object> d = value as IDictionary<string, object>;
if (d != null)
{
foreach (KeyValuePair<string, object> entry in d)
{
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 object GetDeserializedObject(ControllerContext controllerContext)
{
if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
{
// not JSON request
return null;
}

StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
string bodyText = reader.ReadToEnd();
if (String.IsNullOrEmpty(bodyText))
{
// no JSON data
return null;
}

JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = 2147483647;
object jsonData = serializer.DeserializeObject(bodyText);
return jsonData;
}

public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}

object jsonData = GetDeserializedObject(controllerContext);
if (jsonData == null)
{
return null;
}

Dictionary<string, object> backingStore = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
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;
}
}

与默认工厂相比,我所做的唯一修改是添加以下行:

serializer.MaxJsonLength = 2147483647;

不幸的是,这个工厂根本不可扩展,密封的东西,所以我不得不重新创建它。

在你的Application_Start :

ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<System.Web.Mvc.JsonValueProviderFactory>().FirstOrDefault());
ValueProviderFactories.Factories.Add(new MyJsonValueProviderFactory());

关于c# - 反序列化大型 json 对象的 JsonMaxLength 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9943727/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com