簡體   English   中英

枚舉流利驗證只接受字符串

[英]Enum fluent validation to accept only string

下面是我的枚舉

public enum IdentifierType
{
    Customer = 1,
    Manager = 2,
    Director = 3
}

在 .Net 核心中使用流暢的驗證,是否可以在請求中傳遞 1/"1" 或 2/"2" 或 3/"3" 時返回驗證錯誤進行驗證?

通過“客戶”或“經理”等應該可以正常工作。

我知道 C# 枚舉類型是“int”,但首先考慮一下這是否可行?

startup.cs 中的設置:Validator 在我的轉換器之前注冊。

services.AddControllers()
        .AddFluentValidation(configuration =>
        {
          configuration.RegisterValidatorsFromAssemblyContaining<Startup>();
        })
          .ConfigureApiBehaviorOptions(opt => { opt.SuppressModelStateInvalidFilter = true; })
          .AddJsonOptions(serializerOption =>
          {
            serializerOption.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
            serializerOption.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
            serializerOption.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
          });

API 使用 postman 的附加行為

在此處輸入圖像描述 在此處輸入圖像描述

MVC 框架必須將 JSON 轉換為 class,FluentValidation 才能工作。

但是,您可以配置 MVC 以首先驗證它。

要允許任何 ASP.NET MVC Core 應用程序中的內置 JSON 序列化程序允許將字符串轉換為枚舉,您需要在應用程序啟動時添加JsonStringEnumConverter轉換器。 此轉換器還有一個參數,您可以將其設置為 false 以禁止 integer 值。 例如:

services
    .AddMvc()
    .AddJsonOptions(opts =>
    {
        opts.JsonSerializerOptions.Converters.Add(
            new JsonStringEnumConverter(allowIntegerValues: false));
    })

由於似乎 '' 不會阻止將 int 作為字符串傳遞,因此您可以編寫自己的轉換器。 例如,這樣的事情會起作用:

public class IdentifierTypeConverter : JsonConverter<IdentifierType>{
    public override IdentifierType Read(ref Utf8JsonReader reader, 
        Type typeToConvert, JsonSerializerOptions options)
    {
        var value = reader.GetString();
        
        if(value == null)
        {
            throw new Exception("No null values thanks!");  
        }
        
        if(int.TryParse(value, out var _))
        {
            throw new Exception("No numbers thanks!");
        }
        
        return (IdentifierType)Enum.Parse(typeof(IdentifierType), value);
    }

    public override void Write(Utf8JsonWriter writer, IdentifierType value, 
        JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString());
    }
}

您可以使用 JsonConverterFactory 制作通用版本。 首先使轉換器通用:

public class EnumConverter<TEnum> : JsonConverter<TEnum> where TEnum : Enum
{
 public override bool CanConvert(Type typeToConvert) => typeToConvert.IsEnum;

    public override TEnum Read(ref Utf8JsonReader reader, 
        Type typeToConvert, JsonSerializerOptions options)
    {
        var value = reader.GetString();

        if (value == null)
        {
            throw new Exception("No null values thanks!");
        }

        if (int.TryParse(value, out var _))
        {
            throw new Exception("No numbers thanks!");
        }

        return (TEnum)Enum.Parse(typeof(TEnum), value);
    }

    public override void Write(Utf8JsonWriter writer, TEnum value, 
        JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString());
    }
}

並讓你的工廠:

public class EnumConverterFactory : JsonConverterFactory
{
    public override bool CanConvert(Type typeToConvert) => typeToConvert.IsEnum;

    public override JsonConverter? CreateConverter(Type typeToConvert, 
        JsonSerializerOptions options)
    {
        
        JsonConverter converter = (JsonConverter)Activator.CreateInstance(
            typeof(EnumConverter<>).MakeGenericType(typeToConvert))!;

        return converter;
    }
}

現在添加工廠:

opts.JsonSerializerOptions.Converters.Add(new EnumConverterFactory());

據我所知,流暢的驗證沒有直接的解決方案來解決您的問題。 但是,我會按如下所述處理這種情況:

在下面的代碼中,我創建了兩個屬性 - IdentifierType字段是公共的,它將接受來自您的客戶端的字符串值。 另一個字段是一個enum ,它可以在您的項目內部使用。

public class YourRequestModel
{
   internal IdentifierType IdType
   {
     get
     {
        return Enum.Parse<IdentifierType>(IdentifierType);
     }
    }
   public string IdentifierType { get; }
}

在進行流暢驗證時,僅針對字符串值驗證輸入。

public class YourRequestModelValidator: AbstractValidator<YourRequestModel> 
{
  RuleFor(x => x.IdentifierType)
            .IsEnumName(typeof(IdentifierType), caseSensitive: false);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM