.NET中如何忽略数据注解里枚举类型的大小写敏感
问题描述
我正在开发REST API,POST请求的JSON输入包含多个参数,其中一个是用户语言。
JSON示例:
{ "userlanguage":"en" }
我为所有语言创建了Enum类(仅提供英语、印地语作为参考):
public enum Language { EN = 0, HI =1 }
验证类使用了EnumDataType和Required数据注解:
public class UserDetails { [Required] [EnumDataType(typeof(Language), ErrorMessage = "Invalid Language Supported.")] [JsonProperty("userlanguage")] public string? UserLanguage { get; set; } }
我还创建了扩展类来验证任意类模型:
public static class HttpRequestValidationExtension { public static bool IsValid(this object o, out ICollection<ValidationResult> validationResults) { validationResults = new List<ValidationResult>(); return Validator.TryValidateObject(o, new ValidationContext(o, null, null), validationResults, true); } }
控制器类中的用法:
UserDetails userDetails= JsonConvert.DeserializeObject<UserDetails>(requestBody); if (!userDetails.IsValid(validationResults: out var validationResults)) { string errorMessage = "Bad Request."; int statusCode = 400; return DisplayErrorMessage (statusCode, string.Join("", validationResults.Select(s => s.ErrorMessage).FirstOrDefault()), functionName, string.Join("", validationResults.Select(s => s.MemberNames).FirstOrDefault())); }
问题:
当传入EN时验证成功,但传入en时验证失败,请问有没有办法忽略大小写?
解决方案
方法1:自定义大小写不敏感的枚举验证属性
创建自定义属性替代默认的EnumDataTypeAttribute,在验证逻辑中忽略大小写:
public class CaseInsensitiveEnumDataTypeAttribute : EnumDataTypeAttribute { public CaseInsensitiveEnumDataTypeAttribute(Type enumType) : base(enumType) { } public override bool IsValid(object value) { if (value == null) return true; string stringValue = value.ToString(); return Enum.TryParse(EnumType, stringValue, ignoreCase: true, out _); } }
修改UserDetails类的属性注解:
public class UserDetails { [Required] [CaseInsensitiveEnumDataType(typeof(Language), ErrorMessage = "Invalid Language Supported.")] [JsonProperty("userlanguage")] public string? UserLanguage { get; set; } }
方法2:反序列化时统一转换大小写
通过自定义JsonConverter,在反序列化阶段将语言参数统一转为大写(或小写),匹配枚举命名:
public class CaseInsensitiveStringConverter : JsonConverter<string> { public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer) { string value = reader.Value?.ToString(); return string.IsNullOrEmpty(value) ? value : value.ToUpperInvariant(); } public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer) { writer.WriteValue(value); } }
在UserDetails的属性上应用该转换器:
public class UserDetails { [Required] [EnumDataType(typeof(Language), ErrorMessage = "Invalid Language Supported.")] [JsonProperty("userlanguage")] [JsonConverter(typeof(CaseInsensitiveStringConverter))] public string? UserLanguage { get; set; } }
方法3:修改扩展验证方法,加入大小写忽略逻辑
在现有的IsValid扩展方法中,针对枚举类型的字符串属性单独做大小写不敏感校验:
public static class HttpRequestValidationExtension { public static bool IsValid(this object o, out ICollection<ValidationResult> validationResults) { validationResults = new List<ValidationResult>(); bool baseValid = Validator.TryValidateObject(o, new ValidationContext(o, null, null), validationResults, true); // 额外处理枚举类型的字符串属性,忽略大小写 var enumProperties = o.GetType().GetProperties() .Where(p => p.PropertyType == typeof(string) && p.GetCustomAttribute<EnumDataTypeAttribute>() != null); foreach (var prop in enumProperties) { string value = prop.GetValue(o) as string; if (string.IsNullOrEmpty(value)) continue; var enumAttr = prop.GetCustomAttribute<EnumDataTypeAttribute>(); if (!Enum.TryParse(enumAttr.EnumType, value, ignoreCase: true, out _)) { validationResults.Add(new ValidationResult(enumAttr.ErrorMessage ?? "Invalid enum value.", new[] { prop.Name })); baseValid = false; } } return baseValid; } }
内容的提问来源于stack exchange,提问作者PavanKumar GVVS
相关产品推荐
相关产品推荐

