![](/img/trans.png)
[英]Method signature in ASP.NET Core for AngularJS API request with JSON
[英]ASP.NET Core API JSON serializersettings per request
根据请求中的某些值(标题或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响应必须以两种不同的方式序列化,而且反序列化必须以两种不同的方式完成。
这有两个选择:
您通过services.AddMvc().AddJsonOptions()
设置的选项services.AddMvc().AddJsonOptions()
在DI中注册,您可以将其注入您的控制器和服务:
public HomeController(IOptions<MvcJsonOptions> optionsAccessor)
{
JsonSerializerSettings jsonSettings = optionsAccessor.Value.SerializerSettings;
}
要按请求覆盖这些序列化设置,您可以使用Json
方法或创建JsonResult
实例:
public IActionResult Get()
{
return Json(data, new JsonSerializerSettings());
return new JsonResult(data, new JsonSerializerSettings());
}
public class ModifyResultFilter : IAsyncResultFilter
{
public ModifyResultFilter(IOptions<MvcJsonOptions> 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中注册过滤器。
感谢您的评论和解答。 我找到了一个带输入和输出格式的解决方案。 感谢http://rovani.net/Explicit-Model-Constructor/指出我正确的方向。
我创建了自己的输入和输出格式,它继承自JsonInputFormatter
以保持相同的功能。
在构造函数中,我设置了支持的mediatype(使用了一些类似于JSON的现有类型)。
还必须覆盖CreateJsonSerializer
以将ContractResolver
设置为所需的(可以实现单例)。
一定要做到这样,因为改变serializerSettings
在构造函数将改变所有输入/ outputformatters的serializersettings,意味着默认的JSON格式化也将使用新的合同解析器。
这样做也意味着你可以通过AddMvc().AddJsonOption()
设置一些默认的JSON选项AddMvc().AddJsonOption()
示例inputformatter,outputformatter使用相同的原则:
static MediaTypeHeaderValue protoMediaType = MediaTypeHeaderValue.Parse("application/jsonfull");
public JsonFullInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings, ArrayPool<char> 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<MvcOptions>
{
private readonly ILoggerFactory _loggerFactory;
private readonly JsonSerializerSettings _jsonSerializerSettings;
private readonly ArrayPool<char> _charPool;
private readonly ObjectPoolProvider _objectPoolProvider;
public YourMvcOptionsSetup(ILoggerFactory loggerFactory, IOptions<MvcJsonOptions> jsonOptions, ArrayPool<char> charPool, ObjectPoolProvider objectPoolProvider)
{
//Validate parameters and set fields
}
public void Configure(MvcOptions options)
{
var jsonFullInputFormatter = new JsonFullInputFormatter(
_loggerFactory.CreateLogger<JsonFullInputFormatter>(),
_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<IConfigureOptions<MvcOptions>, 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(获取调用)和ContentType(post / put调用)标头来获取完整的JSON属性名称。 我们通过jQuery的$.ajaxSetup(
。
$.ajaxSetup({
contentType: "application/jsonfull; charset=utf-8",
headers: { 'Accept': 'application/jsonfull' }
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.