使用时是否可以注册/使用“全局” 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());
});

10-08 14:15