C# 在 ASP.NET MVC 中设置默认的 JSON 序列化程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14591750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setting the default JSON serializer in ASP.NET MVC
提问by John
I'm working on an existing application that has been partially converted over to MVC. Whenever a controller responds with a JSON ActionResult, the enums are sent as numbers opposed to the string name. It sounds like the default serializer should be JSON.Net, which should be sending the enums over as their names opposed to the integer representation, but that's not the case here.
我正在处理一个已部分转换为 MVC 的现有应用程序。每当控制器以 JSON ActionResult 响应时,枚举将作为与字符串名称相反的数字发送。听起来默认序列化程序应该是 JSON.Net,它应该将枚举作为它们的名称而不是整数表示发送,但这里的情况并非如此。
Am I missing a web.config setting that sets this as the default serializer? Or is there another setting that needs to be changed?
我是否缺少将其设置为默认序列化程序的 web.config 设置?或者是否还有其他设置需要更改?
采纳答案by nemesv
In ASP.Net MVC4 the default JavaScript serializer which is used in the JsonResult
class is still the JavaScriptSerializer(you can check it in the code)
在 ASP.Net MVC4 中,JsonResult
类中使用的默认 JavaScript 序列化器仍然是JavaScriptSerializer(您可以在代码中检查它)
I think you have confused it with the ASP.Net Web.API where JSON.Net is the default JS serializer but MVC4 doesn't use it.
我认为您已经将它与 ASP.Net Web.API 混淆了,其中 JSON.Net 是默认的 JS 序列化程序,但 MVC4 不使用它。
So you need to configure JSON.Net to work with MVC4 (basically you need to create your own JsonNetResult
), there are plenty of articles about it:
所以你需要配置 JSON.Net 与 MVC4 一起工作(基本上你需要创建自己的JsonNetResult
),有很多关于它的文章:
- ASP.NET MVC and Json.NET
- Using JSON.NET as the default JSON serializer in ASP.NET MVC 3 - is it possible?
If you also want to use JSON.Net for controller action parameters so during the model binding then you need write your own ValueProviderFactory
implementation.
如果您还想在模型绑定期间将 JSON.Net 用于控制器操作参数,那么您需要编写自己的ValueProviderFactory
实现。
And you need to register your implementation with:
你需要注册你的实现:
ValueProviderFactories.Factories
.Remove(ValueProviderFactories.Factories
.OfType<JsonValueProviderFactory>().Single());
ValueProviderFactories.Factories.Add(new MyJsonValueProviderFactory());
You can use the built in JsonValueProviderFactory
as an example or this article: ASP.NET MVC 3 – Improved JsonValueProviderFactory using Json.Net
您可以使用内置JsonValueProviderFactory
作为示例或这篇文章: ASP.NET MVC 3 – 使用 Json.Net 改进 JsonValueProviderFactory
回答by Maxim Gershkovich
ASP.NET MVC 5 Fix:
ASP.NET MVC 5 修复:
I wasn't ready to change to Json.NET just yet and in my case the error was occurring during the request. Best approach in my scenario was modifying the actual JsonValueProviderFactory
which applies the fix to the global project and can be done by editing the global.cs
file as such.
我还没有准备好更改为 Json.NET,在我的情况下,错误发生在请求期间。在我的场景中,最好的方法是修改将JsonValueProviderFactory
修复应用到全局项目的实际,并且可以通过这样编辑global.cs
文件来完成。
JsonValueProviderConfig.Config(ValueProviderFactories.Factories);
add a web.config entry:
添加一个 web.config 条目:
<add key="aspnet:MaxJsonLength" value="20971520" />
and then create the two following classes
然后创建以下两个类
public class JsonValueProviderConfig
{
public static void Config(ValueProviderFactoryCollection factories)
{
var jsonProviderFactory = factories.OfType<JsonValueProviderFactory>().Single();
factories.Remove(jsonProviderFactory);
factories.Add(new CustomJsonValueProviderFactory());
}
}
This is basically an exact copy of the default implementation found in System.Web.Mvc
but with the addition of a configurable web.config appsetting value aspnet:MaxJsonLength
.
这基本上是在 中找到的默认实现的精确副本,System.Web.Mvc
但添加了可配置的 web.config appsetting 值aspnet:MaxJsonLength
。
public class CustomJsonValueProviderFactory : ValueProviderFactory
{
/// <summary>Returns a JSON value-provider object for the specified controller context.</summary>
/// <returns>A JSON value-provider object for the specified controller context.</returns>
/// <param name="controllerContext">The controller context.</param>
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
object deserializedObject = CustomJsonValueProviderFactory.GetDeserializedObject(controllerContext);
if (deserializedObject == null)
return null;
Dictionary<string, object> strs = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
CustomJsonValueProviderFactory.AddToBackingStore(new CustomJsonValueProviderFactory.EntryLimitedDictionary(strs), string.Empty, deserializedObject);
return new DictionaryValueProvider<object>(strs, CultureInfo.CurrentCulture);
}
private static object GetDeserializedObject(ControllerContext controllerContext)
{
if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
return null;
string fullStreamString = (new StreamReader(controllerContext.HttpContext.Request.InputStream)).ReadToEnd();
if (string.IsNullOrEmpty(fullStreamString))
return null;
var serializer = new JavaScriptSerializer()
{
MaxJsonLength = CustomJsonValueProviderFactory.GetMaxJsonLength()
};
return serializer.DeserializeObject(fullStreamString);
}
private static void AddToBackingStore(EntryLimitedDictionary backingStore, string prefix, object value)
{
IDictionary<string, object> strs = value as IDictionary<string, object>;
if (strs != null)
{
foreach (KeyValuePair<string, object> keyValuePair in strs)
CustomJsonValueProviderFactory.AddToBackingStore(backingStore, CustomJsonValueProviderFactory.MakePropertyKey(prefix, keyValuePair.Key), keyValuePair.Value);
return;
}
IList lists = value as IList;
if (lists == null)
{
backingStore.Add(prefix, value);
return;
}
for (int i = 0; i < lists.Count; i++)
{
CustomJsonValueProviderFactory.AddToBackingStore(backingStore, CustomJsonValueProviderFactory.MakeArrayKey(prefix, i), lists[i]);
}
}
private class EntryLimitedDictionary
{
private static int _maximumDepth;
private readonly IDictionary<string, object> _innerDictionary;
private int _itemCount;
static EntryLimitedDictionary()
{
_maximumDepth = CustomJsonValueProviderFactory.GetMaximumDepth();
}
public EntryLimitedDictionary(IDictionary<string, object> innerDictionary)
{
this._innerDictionary = innerDictionary;
}
public void Add(string key, object value)
{
int num = this._itemCount + 1;
this._itemCount = num;
if (num > _maximumDepth)
{
throw new InvalidOperationException("The length of the string exceeds the value set on the maxJsonLength property.");
}
this._innerDictionary.Add(key, value);
}
}
private static string MakeArrayKey(string prefix, int index)
{
return string.Concat(prefix, "[", index.ToString(CultureInfo.InvariantCulture), "]");
}
private static string MakePropertyKey(string prefix, string propertyName)
{
if (string.IsNullOrEmpty(prefix))
{
return propertyName;
}
return string.Concat(prefix, ".", propertyName);
}
private static int GetMaximumDepth()
{
int num;
NameValueCollection appSettings = ConfigurationManager.AppSettings;
if (appSettings != null)
{
string[] values = appSettings.GetValues("aspnet:MaxJsonDeserializerMembers");
if (values != null && values.Length != 0 && int.TryParse(values[0], out num))
{
return num;
}
}
return 1000;
}
private static int GetMaxJsonLength()
{
int num;
NameValueCollection appSettings = ConfigurationManager.AppSettings;
if (appSettings != null)
{
string[] values = appSettings.GetValues("aspnet:MaxJsonLength");
if (values != null && values.Length != 0 && int.TryParse(values[0], out num))
{
return num;
}
}
return 1000;
}
}