Asp.net core mvc ASP.NET MVC验证返回小写属性名

Asp.net core mvc ASP.NET MVC验证返回小写属性名,asp.net-core-mvc,asp.net-core-webapi,Asp.net Core Mvc,Asp.net Core Webapi,在我的ASP.NET MVC核心web应用程序中,属性的Json序列化设置为驼峰大小写(首字母小写): 客户端的序列化正在按预期工作 但是,当javascript客户端试图发布数据而该数据无效时,他会收到一条带有大写字母属性的验证消息,该验证消息是ModelState: {"Info":["The Info field is required."]} 是否有办法使ASP.NET在ModelState的验证消息中返回小写属性以反映命名策略?解决方案是禁用自动api验证筛选器,并使用验证消息创建自

在我的ASP.NET MVC核心web应用程序中,属性的Json序列化设置为驼峰大小写(首字母小写):

客户端的序列化正在按预期工作

但是,当javascript客户端试图发布数据而该数据无效时,他会收到一条带有大写字母属性的验证消息,该验证消息是
ModelState

{"Info":["The Info field is required."]}

是否有办法使ASP.NET在
ModelState
的验证消息中返回小写属性以反映命名策略?

解决方案是禁用自动api验证筛选器,并使用验证消息创建自己的json结果:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressModelStateInvalidFilter = true; 
});

有一个更简单的解决办法。使用Fluent Validator的
ValidatorOptions.Global.PropertyNameResolver
。取自并转换为C#8和C#9:

在Startup.cs中,ConfigureServices使用:

services
    .AddControllers()
    .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
    .AddFluentValidation(fv =>
    {
        fv.RegisterValidatorsFromAssemblyContaining<MyValidator>();
        // Convert property names to camelCase as Asp.Net Core does https://github.com/FluentValidation/FluentValidation/issues/226 
        ValidatorOptions.Global.PropertyNameResolver = CamelCasePropertyNameResolver.ResolvePropertyName;
    })
    .AddNewtonsoftJson(NewtonsoftUtils.SetupNewtonsoftOptionsDefaults);
服务
.AddControllers()
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.AddFluentValidation(fv=>
{
fv.RegisterValidatorsFromAssemblyContaining();
//将属性名称转换为camelCase,就像Asp.Net核心所做的那样https://github.com/FluentValidation/FluentValidation/issues/226 
ValidatorOptions.Global.PropertyNameResolver=CamelCasePropertyNameResolver.ResolvePropertyName;
})
.AddNewtonsoftJson(NewtonsoftUtils.setupnewtonsoftoptions默认值);
和解析器本身:

/// <summary>
/// Convert property names to camelCase as Asp.Net Core does 
/// https://github.com/FluentValidation/FluentValidation/issues/226
/// </summary>
public class CamelCasePropertyNameResolver
{

    public static string? ResolvePropertyName(Type type, MemberInfo memberInfo, LambdaExpression expression)
    {
        return ToCamelCase(DefaultPropertyNameResolver(type, memberInfo, expression));
    }

    private static string? DefaultPropertyNameResolver(Type type, MemberInfo memberInfo, LambdaExpression expression)
    {
        if (expression != null)
        {
            var chain = PropertyChain.FromExpression(expression);
            if (chain.Count > 0)
            {
                return chain.ToString();
            }
        }

        if (memberInfo != null)
        {
            return memberInfo.Name;
        }

        return null;
    }

    private static string? ToCamelCase(string? s)
    {
        if (string.IsNullOrEmpty(s) || !char.IsUpper(s[0]))
        {
            return s;
        }

        var chars = s.ToCharArray();

        for (var i = 0; i < chars.Length; i++)
        {
            if (i == 1 && !char.IsUpper(chars[i]))
            {
                break;
            }

            var hasNext = (i + 1 < chars.Length);
            if (i > 0 && hasNext && !char.IsUpper(chars[i + 1]))
            {
                break;
            }

            chars[i] = char.ToLower(chars[i], CultureInfo.InvariantCulture);
        }

        return new string(chars);
    }
}
//
///将属性名称转换为camelCase,就像Asp.Net核心所做的那样
/// https://github.com/FluentValidation/FluentValidation/issues/226
/// 
公共类CamelCasePropertyNameResolver
{
公共静态字符串?ResolvePropertyName(类型类型、MemberInfo MemberInfo、LambdaExpression表达式)
{
返回到CamelCase(DefaultPropertyNameResolver(类型、成员信息、表达式));
}
私有静态字符串?DefaultPropertyNameResolver(类型类型、MemberInfo MemberInfo、LambdaExpression表达式)
{
if(表达式!=null)
{
var chain=PropertyChain.FromExpression(表达式);
如果(chain.Count>0)
{
返回链.ToString();
}
}
if(memberInfo!=null)
{
返回memberInfo.Name;
}
返回null;
}
专用静态字符串?ToCamelCase(字符串?s)
{
if(string.IsNullOrEmpty(s)| |!char.IsUpper(s[0]))
{
返回s;
}
var chars=s.ToCharArray();
对于(变量i=0;i0&&hasNext&&!char.IsUpper(chars[i+1]))
{
打破
}
chars[i]=char.ToLower(chars[i],CultureInfo.InvariantCulture);
}
返回新字符串(字符);
}
}
public static string ToCamelCase(this string name)
{
    if (string.IsNullOrEmpty(name))
    {
        return name;
    }
    return name.Substring(0, 1).ToLower() + name.Substring(1);
}
services
    .AddControllers()
    .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
    .AddFluentValidation(fv =>
    {
        fv.RegisterValidatorsFromAssemblyContaining<MyValidator>();
        // Convert property names to camelCase as Asp.Net Core does https://github.com/FluentValidation/FluentValidation/issues/226 
        ValidatorOptions.Global.PropertyNameResolver = CamelCasePropertyNameResolver.ResolvePropertyName;
    })
    .AddNewtonsoftJson(NewtonsoftUtils.SetupNewtonsoftOptionsDefaults);
/// <summary>
/// Convert property names to camelCase as Asp.Net Core does 
/// https://github.com/FluentValidation/FluentValidation/issues/226
/// </summary>
public class CamelCasePropertyNameResolver
{

    public static string? ResolvePropertyName(Type type, MemberInfo memberInfo, LambdaExpression expression)
    {
        return ToCamelCase(DefaultPropertyNameResolver(type, memberInfo, expression));
    }

    private static string? DefaultPropertyNameResolver(Type type, MemberInfo memberInfo, LambdaExpression expression)
    {
        if (expression != null)
        {
            var chain = PropertyChain.FromExpression(expression);
            if (chain.Count > 0)
            {
                return chain.ToString();
            }
        }

        if (memberInfo != null)
        {
            return memberInfo.Name;
        }

        return null;
    }

    private static string? ToCamelCase(string? s)
    {
        if (string.IsNullOrEmpty(s) || !char.IsUpper(s[0]))
        {
            return s;
        }

        var chars = s.ToCharArray();

        for (var i = 0; i < chars.Length; i++)
        {
            if (i == 1 && !char.IsUpper(chars[i]))
            {
                break;
            }

            var hasNext = (i + 1 < chars.Length);
            if (i > 0 && hasNext && !char.IsUpper(chars[i + 1]))
            {
                break;
            }

            chars[i] = char.ToLower(chars[i], CultureInfo.InvariantCulture);
        }

        return new string(chars);
    }
}