FromQuery参数从camelCase/PascalCase到snake_case .Net Core

Car*_*ito 2 c# json.net .net-core asp.net-core

我已经尝试过这里的解决方案:How toproperlysetupsnakecaseJSONfordotnetcoreapi? 但似乎这仅适用于请求/响应有效负载。有没有办法在我的 [FromQuery] 参数上强制使用 Snake_case 格式?

目前这就是我目前所拥有的 在此输入图像描述

Ren*_*ena 10

您所做的是关于 asp.net core 中的 json 序列化,但您想要的是更改 Swagger UI。它们是完全不同的东西。

第一种方法,您可以添加属性,例如:[FromQuery(Name = "account_number")]

或者你可以自定义一个属性以避免编写snake_case:

public class CustomFromQueryAttribute : FromQueryAttribute
{
    public CustomFromQueryAttribute(string name)
    {
        Name = name.ToSnakeCase();
    }
}
Run Code Online (Sandbox Code Playgroud)

自定义ToSnakeCase字符串扩展:

public static class StringExtensions
{
    public static string ToSnakeCase(this string o) =>
           Regex.Replace(o, @"(\w)([A-Z])", "$1_$2").ToLower();
}
Run Code Online (Sandbox Code Playgroud)

用法:

public voidGet([CustomFromQuery("AccountNumber")]string AccountNumber)
Run Code Online (Sandbox Code Playgroud)

笔记:

实际上这种方式相当于使用public voidGet(string account_number),所以 Swagger UI 发生了变化。


第二种方式,您可以IOperationFilter像下面这样自定义来更改 Swagger UI:

public class SnakecasingParameOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        if (operation.Parameters == null) operation.Parameters = new List<OpenApiParameter>();
        else { 
            foreach(var item in operation.Parameters)
            {             
                 item.Name = item.Name.ToSnakeCase();
            }              
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

注册服务如下:

services.AddSwaggerGen(c =>
{
    c.OperationFilter<SnakecasingParameOperationFilter>();
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi5_0", Version = "v1" });
});
Run Code Online (Sandbox Code Playgroud)

但是这种方式将请求查询字符串更改为蛇形大小写,其中有一个额外的_,它与后端参数不匹配。因此,您还需要自定义值提供程序来查找蛇形查询参数:

SnakeCaseQueryValueProvider:

 public class SnakeCaseQueryValueProvider : QueryStringValueProvider, IValueProvider
{
    public SnakeCaseQueryValueProvider(
        BindingSource bindingSource,
        IQueryCollection values,
        CultureInfo culture)
        : base(bindingSource, values, culture)
    {
    }

    public override bool ContainsPrefix(string prefix)
    {
        return base.ContainsPrefix(prefix.ToSnakeCase());
    }

    public override ValueProviderResult GetValue(string key)
    {
        return base.GetValue(key.ToSnakeCase());            
    }
}
Run Code Online (Sandbox Code Playgroud)

我们还必须为我们的价值提供者实现一个工厂:

public class SnakeCaseQueryValueProviderFactory : IValueProviderFactory
{
    public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        var valueProvider = new SnakeCaseQueryValueProvider(
            BindingSource.Query,
            context.ActionContext.HttpContext.Request.Query,
            CultureInfo.CurrentCulture);

        context.ValueProviders.Add(valueProvider);

        return Task.CompletedTask;
    }
}
Run Code Online (Sandbox Code Playgroud)

注册服务:

services.AddControllers(options =>
{
    options.ValueProviderFactories.Add(new SnakeCaseQueryValueProviderFactory()); //add this...
}).AddNewtonsoftJson(options =>
{
    options.SerializerSettings.ContractResolver = new DefaultContractResolver
    {
        NamingStrategy = new SnakeCaseNamingStrategy()
    };
});
Run Code Online (Sandbox Code Playgroud)