Poo*_*eld 8 c# enums asp.net-core-webapi
[Required]当 JSON 请求没有为枚举属性提供正确的值时,是否可以返回属性错误消息?
例如,我有一个包含AddressType枚举类型属性的 POST 消息模型:
public class AddressPostViewModel
{
[JsonProperty("addressType")]
[Required(ErrorMessage = "Address type is required.")]
public AddressType AddressType { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
该AddressType枚举接受两个值:
[JsonConverter(typeof(StringEnumConverter))]
public enum AddressType
{
[EnumMember(Value = "Dropship")]
Dropship,
[EnumMember(Value = "Shipping")]
Shipping
}
Run Code Online (Sandbox Code Playgroud)
我注意到(或者实际上我的 QA 团队注意到)如果请求消息 JSON 包含空字符串或 null AddressType,则错误消息不是预期的Address type is required.消息。相反,错误消息是一个有点不友好的解析错误。
例如,如果请求 JSON 如下所示:
{ "addressType": "" }
Run Code Online (Sandbox Code Playgroud)
然后验证框架自动生成的错误如下所示:
{
"message": "Validation Failed",
"errors": [
{
"property": "addressType",
"message": "Error converting value \"\" to type 'MyNamespace.AddressType'. Path 'addressType', line 4, position 19."
}
]
}
Run Code Online (Sandbox Code Playgroud)
[Required]如果有人不包含枚举的有效值,有没有办法确保返回属性的错误消息?
选项 1:使用自定义 RequiredEnum 属性并避免 JsonConverter 属性
不要将 JsonConverter 放在 AddressType 枚举上。此 StringToEnum 未能将 string.Empty 映射到 enum 值,并抛出此错误消息。
取而代之的是,您可以编写自定义所需的枚举验证器,如下所示。
using System;
using System.ComponentModel.DataAnnotations;
public class RequiredEnumFieldAttribute: RequiredAttribute
{
public override bool IsValid(object value)
{
if (value == null)
{
return false;
}
var type = value.GetType();
return type.IsEnum && Enum.IsDefined(type, value);
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以像下图一样使用它:
public class AddressPostViewModel
{
[JsonProperty("addressType")]
[RequiredEnumField(ErrorMessage = "Address type is required.")]
public AddressType AddressType { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
选项 2:为 AddressType 使用自定义 JsonConverter
添加一个从 StringEnumConverter 派生的自定义 CustomStringToEnumConverter。
如果 JSON 中的值为空,则此方法将引发错误。
public class CustomStringToEnumConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (string.IsNullOrEmpty(reader.Value.ToString()))
throw new Exception("Address not provided");
return base.ReadJson(reader, objectType, existingValue, serializer);
}
}
Run Code Online (Sandbox Code Playgroud)
使用这个 jsonConverter 而不是默认的 StringEnumConverter 如下所示
[JsonConverter(typeof(CustomStringToEnumConverter))]
public enum AddressType
{
}
Run Code Online (Sandbox Code Playgroud)
我已经想出了一个满足我的要求的解决方案,尽管代码让我有点畏缩。
我将属性[Required]的属性保留AddressType在视图模型中。令人畏缩的部分是我必须制作该财产nullable:
public class AddressPostViewModel
{
[JsonProperty("addressType")]
[Required(ErrorMessage = "Address type is required.")]
public AddressType? AddressType { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在AttributeType枚举本身上,我按照 @Manoj Choudhari 的建议StringEnumConverter用自定义替换了该属性:JsonConverter
[JsonConverter(typeof(CustomStringToEnumConverter))]
public enum AddressType
{
[EnumMember(Value = "Dropship")]
Dropship,
[EnumMember(Value = "Shipping")]
Shipping
}
Run Code Online (Sandbox Code Playgroud)
这是CustomStringToEnumConverter:
public class CustomStringToEnumConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (string.IsNullOrEmpty(reader.Value?.ToString()))
{
return null;
}
object parsedEnumValue;
var isValidEnumValue = Enum.TryParse(objectType.GenericTypeArguments[0], reader.Value.ToString(), true, out parsedEnumValue);
if (isValidEnumValue)
{
return parsedEnumValue;
}
else
{
return null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
可以CustomStringToEnumConverter处理空字符串、空值和无效字符串。如果遇到无效的枚举值,则会返回null该值,然后在发生必需的字段验证(魔术)时捕获该值,并RequiredAttribute在 JSON 响应中显示错误消息。
虽然我不喜欢使类型可为空,但如果请求 JSON 中的值错误,AttributeType我的 API 的使用者将看到一致的验证消息。AttributeType