使用时是否可以注册/使用“全局” ContractResolver
ApsNetCore.JsonPatch(2.1.1)包?
我遇到了一个路径无法解析的问题,因为模型中的属性在PascalCase中,而JsonPatch中的路径在SnakeCase中。
在这种情况下,我必须将Startup.cs文件中JsonPatchDocument上的ContractResolver设置为Default / Globally注册的ContractResolver。
它可以工作,但是我必须对要实施的每个修补程序路线都执行此操作。
启动配置:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
})
}
控制器:
[HttpPatch("{id}"]
[Consumes(MediaTypeNames.Application.Json)]
public async Task<IActionResult> Patch(string id,
[FromBody] JsonPatchDocument<Entity> patchEntity)
{
...
patchEntity.ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
};
patchEntity.ApplyTo(entity);
...
最佳答案
似乎没有简单的方法来影响创建ContractResolver
实例时使用的JsonPatchDocument<T>
。此类的实例由TypedJsonPatchDocumentConverter
创建,如以下代码片段所示:
var container = Activator.CreateInstance(
objectType,
targetOperations,
new DefaultContractResolver());
显然,在创建
DefaultContractResolver
实例时,JsonPatchDocument<T>
被硬编码为第二个参数。使用ASP.NET Core MVC时处理此问题的一种方法是使用Action Filter,它允许对传递给操作的任何参数进行更改。这是一个基本示例:
public class ExampleActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext ctx)
{
// Find a single argument we can treat as IJsonPatchDocument.
var jsonPatchDocumentActionArgument = ctx.ActionArguments.SingleOrDefault(
x => typeof(IJsonPatchDocument).IsAssignableFrom(x.Value.GetType()));
// Here, jsonPatchDocumentActionArgument.Value will be null if none was found.
var jsonPatchDocument = jsonPatchDocumentActionArgument.Value as IJsonPatchDocument;
if (jsonPatchDocument != null)
{
jsonPatchDocument.ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
};
}
}
}
此处传递的
ActionExecutingContext
类包含ActionArguments
属性,在此示例中,该属性用于尝试查找类型为IJsonPatchDocument
的参数。如果找到一个,我们将相应地覆盖ContractResolver
。为了使用这个新的动作过滤器,您可以将其添加到控制器,动作或全局注册。以下是在全球范围内进行注册的方法(其他选择有很多答案,因此在这里我不会深入探讨):
services.AddMvc(options =>
{
options.Filters.Add(new ExampleActionFilterAttribute());
});