每个请求的ASP.NET Core API JSON serializersettings

根据请求中的某些值(标题或在url中),我想更改DTO对象的序列化。 为什么? 好吧,我已经将[JsonProperty("A")]到我的DTO,但是根据客户端(网站或移动应用程序),它是否要使用该属性。 我开始了

 services .AddMvc() .AddJsonOptions(opt => { #if DEBUG opt.SerializerSettings.ContractResolver = new NoJsonPropertyNameContractResolver(); #endif } 

因此,在调试时,我获得了具有完整属性名称的JSON。 我使用JsonProperty属性来缩短响应JSON,这适用于移动应用程序(Xamarin),后者反序列化回到相同的DTO。 但现在我有一个网站使用相同的API通过jQuery获取数据,但在那里我想处理DTO的完整属性名称,而不是JsonProperty属性中给出的名称。 网站和WebApi位于同一台服务器上,因此如果响应更大,则没有问题。

我开始使用中间件类来响应客户标头值,这可行,但现在我不知道如何进入JSON SerializerSettings。 搜索网络但找不到它。

在搜索时我已经阅读过关于InputFormatters和OutputFormatters,以及内容协商,但我不知道我必须去哪个方向。

我不想使用不同的设置两次部署相同的API。
如果能有所帮助,我能够改变routesconfig之类的东西。

更新
不仅JSON响应必须以两种不同的方式序列化,而且反序列化必须以两种不同的方式完成。

这有两个选择:

1.手动格式化

您通过services.AddMvc().AddJsonOptions()设置的选项services.AddMvc().AddJsonOptions()在DI中注册,您可以将其注入您的控制器和服务:

 public HomeController(IOptions optionsAccessor) { JsonSerializerSettings jsonSettings = optionsAccessor.Value.SerializerSettings; } 

要按请求覆盖这些序列化设置,您可以使用Json方法或创建JsonResult实例:

 public IActionResult Get() { return Json(data, new JsonSerializerSettings()); return new JsonResult(data, new JsonSerializerSettings()); } 

2.结果筛选器替换JSON输出

 public class ModifyResultFilter : IAsyncResultFilter { public ModifyResultFilter(IOptions optionsAccessor) { _globalSettings = optionsAccessor.Value.SerializerSettings; } public async Task OnResultExecutionAsync( ResultExecutingContext context, ResultExecutionDelegate next) { var originResult = context.Result as JsonResult; context.Result = new JsonResult(originResult.Value, customSettings); await next(); } } 

在动作/控制器上使用它:

 [ServiceFilter(typeof(ModifyResultFilter ))] public IActionResult Index() {} 

或者按照文档中的描述创建自定义属性:

 [ModifyResultAttribute] public IActionResult Index() {} 

不要忘记在DI中注册filter。

感谢您的评论和解答。 我找到了一个带输入和输出格式的解决方案。 感谢http://rovani.net/Explicit-Model-Constructor/指出我正确的方向。

我创建了自己的输入和输出格式,它inheritance自JsonInputFormatter以保持相同的function。
在构造函数中,我设置了支持的mediatype(使用了一些类似于JSON的现有类型)。
还必须覆盖CreateJsonSerializer以将ContractResolver设置为所需的(可以实现单例)。
必须这样做,因为更改构造函数中的serializerSettings会更改所有输入/输出格式的serializersettings,这意味着默认的JSON格式化程序也将使用新的合约解析器。
这样做也意味着你可以通过AddMvc().AddJsonOption()设置一些默认的JSON选项AddMvc().AddJsonOption()

示例inputformatter,outputformatter使用相同的原则:

 static MediaTypeHeaderValue protoMediaType = MediaTypeHeaderValue.Parse("application/jsonfull"); public JsonFullInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings, ArrayPool charPool, ObjectPoolProvider objectPoolProvider) : base(logger, serializerSettings, charPool, objectPoolProvider) { this.SupportedMediaTypes.Clear(); this.SupportedMediaTypes.Add(protoMediaType); } protected override JsonSerializer CreateJsonSerializer() { var serializer = base.CreateJsonSerializer(); serializer.ContractResolver = new NoJsonPropertyNameContractResolver(); return serializer; } 

根据安装类上面提到的URL:

 public class YourMvcOptionsSetup : IConfigureOptions { private readonly ILoggerFactory _loggerFactory; private readonly JsonSerializerSettings _jsonSerializerSettings; private readonly ArrayPool _charPool; private readonly ObjectPoolProvider _objectPoolProvider; public YourMvcOptionsSetup(ILoggerFactory loggerFactory, IOptions jsonOptions, ArrayPool charPool, ObjectPoolProvider objectPoolProvider) { //Validate parameters and set fields } public void Configure(MvcOptions options) { var jsonFullInputFormatter = new JsonFullInputFormatter( _loggerFactory.CreateLogger(), _jsonSerializerSettings, _charPool, _objectPoolProvider ); options.InputFormatters.Add(jsonFullInputFormatter); options.OutputFormatters.Add(new JsonFullOutputFormatter( _jsonSerializerSettings, _charPool )); } 

然后是一个注册它的扩展方法:

 public static class MvcBuilderExtensions { public static IMvcBuilder AddJsonFullFormatters(this IMvcBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } ServiceDescriptor descriptor = ServiceDescriptor.Transient, YourMvcOptionsSetup>(); builder.Services.TryAddEnumerable(descriptor); return builder; } } 

ConfigureServices调用它:

 services.AddMvc(config => { config.RespectBrowserAcceptHeader = true; // To use the JsonFullFormatters if clients asks about it via Accept Header }) .AddJsonFullFormatters() //Add our own JSON Formatters .AddJsonOptions(opt => { //Set up some default options all JSON formatters must use (if any) }); 

现在,我们的Xamarin应用程序可以访问webapi并通过JsonProperty属性设置(短)属性名称来接收JSON。
在网站中,我们可以通过添加Accept(get calls)和ContentType(post / put calls)标头来获取完整的JSON属性名称。 我们通过jQuery的$.ajaxSetup(

 $.ajaxSetup({ contentType: "application/jsonfull; charset=utf-8", headers: { 'Accept': 'application/jsonfull' } });