ASP.NET 核心中的 SnakeCaseNamingStrategy 和 JsonPatch
SnakeCaseNamingStrategy and JsonPatch in ASP.NET Core
有没有办法在使用
ApsNetCore.JsonPatch (2.1.1) 包?
我 运行 遇到路径未解决的问题,因为我的模型中的属性是 PascalCase,但 JsonPatch 中的路径是 SnakeCase。
在这种情况下,我必须将 JsonPatchDocument 上的 ContractResolver 设置为 Startup.cs 文件中 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);
...
似乎没有简单的方法来影响在创建 JsonPatchDocument<T>
的实例时使用的 ContractResolver
。此 class 的实例由 TypedJsonPatchDocumentConverter
创建,如以下代码片段所示:
var container = Activator.CreateInstance(
objectType,
targetOperations,
new DefaultContractResolver());
这里很明显 DefaultContractResolver
在创建 JsonPatchDocument<T>
的实例时被硬编码为第二个参数。
在使用 ASP.NET 核心 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
class包含一个ActionArguments
属性,在本例中用于尝试查找[=20=类型的参数].如果找到,我们会相应地覆盖 ContractResolver
。
为了使用这个新的动作过滤器,您可以将它添加到控制器、动作或全局注册。下面是全局注册的方法(其他选项有很多答案,所以我不会在这里深入探讨):
services.AddMvc(options =>
{
options.Filters.Add(new ExampleActionFilterAttribute());
});
有没有办法在使用 ApsNetCore.JsonPatch (2.1.1) 包?
我 运行 遇到路径未解决的问题,因为我的模型中的属性是 PascalCase,但 JsonPatch 中的路径是 SnakeCase。
在这种情况下,我必须将 JsonPatchDocument 上的 ContractResolver 设置为 Startup.cs 文件中 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);
...
似乎没有简单的方法来影响在创建 JsonPatchDocument<T>
的实例时使用的 ContractResolver
。此 class 的实例由 TypedJsonPatchDocumentConverter
创建,如以下代码片段所示:
var container = Activator.CreateInstance(
objectType,
targetOperations,
new DefaultContractResolver());
这里很明显 DefaultContractResolver
在创建 JsonPatchDocument<T>
的实例时被硬编码为第二个参数。
在使用 ASP.NET 核心 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
class包含一个ActionArguments
属性,在本例中用于尝试查找[=20=类型的参数].如果找到,我们会相应地覆盖 ContractResolver
。
为了使用这个新的动作过滤器,您可以将它添加到控制器、动作或全局注册。下面是全局注册的方法(其他选项有很多答案,所以我不会在这里深入探讨):
services.AddMvc(options =>
{
options.Filters.Add(new ExampleActionFilterAttribute());
});