Fluentvalidation错误消息包含c#属性名而不是客户端json属性名

本文关键字:属性 客户端 json 错误 包含 Fluentvalidation 消息 | 更新日期: 2023-09-27 18:01:21

我有一个c# WebApi项目,我正在使用FluentValidation。用于验证客户端输入的WebApi包。

下面是我的模型类代码,它的c#属性名为"IsPremium"。这个属性的json名称为"isLuxury"。

[Serializable, JsonObject, Validator(typeof(ProductValidator))]
public class Product
{
    [JsonProperty("isLuxury")]
    public bool? IsPremium { get; set; }
}

验证器类是这样的

public class ProductValidator : AbstractValidator<Product>
    {
        public ProductValidator()
        {
            RuleFor(product => product.isPremium).NotNull();
        }
    }

对于这样的请求:http://localhost: 52664/api/产品

请求主体:{"isLuxury":"}

我得到以下错误:

{
  "Message": "The request is invalid.",
  "ModelState": {
    "product.isPremium": [
      "'is Premium' must not be empty."
    ]
  }
}

Fluent在这里选择c#属性名,这对客户端来说没有意义,因为它知道它是"isLuxury"。我怎样才能强制流畅地从json属性而不是c#属性中挑选名字,以提供更好的验证,如"'isLuxury'一定不能为空"?

如果不可能,我将不得不重命名我所有的c#属性有相同的名称,这些json暴露给所有的客户端。如果你有更好的方法来解决这个问题,请建议。

Fluentvalidation错误消息包含c#属性名而不是客户端json属性名

使用OverridePropertyName方法修改验证器类

public class ProductValidator : AbstractValidator<Product>
    {
        public ProductValidator()
        {
            RuleFor(product => product.isPremium).NotNull().OverridePropertyName("isLuxury");
        }
    }

引用:https://github.com/JeremySkinner/FluentValidation/wiki/d.-Configuring-a-Validator overriding-the-default-property-name

或者您可以调用WithName方法,它做类似的事情。如果你想完全重命名属性,我会使用OverridePropertyName方法。

正如Sahil所说,使用OverridePropertyName方法。如果您还将它与此结合使用,它会自动计算出JSON属性名称:

private string GetJsonPropertyName<T>(string propertyName)
{
    string jsonPropertyName =
        typeof(T).GetProperties()
        .Where(p => p.Name == propertyName)
        .Select(p => p.GetCustomAttribute<JsonPropertyAttribute>())
        .Select(jp => jp.PropertyName)
        .FirstOrDefault();
    if (null == jsonPropertyName)
    {
        throw new ArgumentException($"Type {nameof(T)} does not contain a property named {propertyName}");
    }
    return jsonPropertyName;
}

然后像这样使用:

RuleFor(product => product.IsPremium)
    .NotNull()
    .OverridePropertyName(
        GetJsonPropertyName<Product>(nameof(Product.IsPremium))
    );