Is there a way to register/use a "global" ContractResolver when using the the ApsNetCore.JsonPatch (2.1.1) package?
I ran into an issue where the path was not resolved because the properties in my Models are in PascalCase but the path in the JsonPatch is in SnakeCase.
In this case I have to set the ContractResolver on the JsonPatchDocument to the Default/Globally registered ContractResolver in the Startup.cs file.
It works but I would have to do this for every Patch Route I am going to implement.
Startup configuration:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
})
}
Controller:
[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);
...
答案 0 :(得分:2)
似乎没有简单的方法来影响创建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());
});