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

FromQuery parameters from camelCase/PascalCase to snake_case .Net Core

我在这里尝试了解决方案: 但似乎这仅适用于 request/response 有效负载。有没有办法在我的 [FromQuery] 参数上强制使用 snake_case 格式?

目前这是我目前拥有的

您所做的是 json 核心中的 json 序列化,但您想要的是更改 Swagger UI。它们是完全不同的东西。

第一种方式,可以添加如下属性:[FromQuery(Name = "account_number")].

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

public class CustomFromQueryAttribute : FromQueryAttribute
{
    public CustomFromQueryAttribute(string name)
    {
        Name = name.ToSnakeCase();
    }
}

自定义 ToSnakeCase 用于字符串扩展:

public static class StringExtensions
{
    public static string ToSnakeCase(this string o) =>
           Regex.Replace(o, @"(\w)([A-Z])", "_").ToLower();
}

用法:

public voidGet([CustomFromQuery("AccountNumber")]string AccountNumber)

注:

实际上这种方式等于使用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();
            }              
        }
    }
}

像下面这样注册服务:

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

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

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());            
    }
}

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

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;
    }
}

注册服务:

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