枚举作为 ASP.NET Core WebAPI 中的必填字段

[Required]当 JSON 请求没有为枚举属性提供正确的值时,是否可以返回属性错误消息?


例如,我有一个 POST 消息模型,其中包含AddressType一个枚举类型的属性:


public class AddressPostViewModel

{

    [JsonProperty("addressType")]

    [Required(ErrorMessage = "Address type is required.")]

    public AddressType AddressType { get; set; }

}

AddressType枚举接受两个值:


[JsonConverter(typeof(StringEnumConverter))]

public enum AddressType

{

    [EnumMember(Value = "Dropship")]

    Dropship,

    [EnumMember(Value = "Shipping")]

    Shipping

}

我注意到(或者实际上我的 QA 团队注意到)如果请求消息 JSON 包含空字符串或 null AddressType,则错误消息不是预期的Address type is required.消息。相反,错误消息是一个有点不友好的解析错误。


例如,如果请求 JSON 如下所示:


{  "addressType": "" }

然后验证框架自动生成的错误如下所示:


{

    "message": "Validation Failed",

    "errors": [

        {

            "property": "addressType",

            "message": "Error converting value \"\" to type 'MyNamespace.AddressType'. Path 'addressType', line 4, position 19."

        }

    ]

}

[Required]如果有人不包含枚举的有效值,是否有办法确保返回属性的错误消息?


慕哥6287543
浏览 307回答 4
4回答

开心每一天1111

选项 1:使用自定义 RequiredEnum 属性并避免 JsonConverter 属性不要将 JsonConverter 放在 AddressType 枚举上。此 StringToEnum 无法将 string.Empty 映射到枚举值,并抛出此错误消息。取而代之的是,您可以编写一个自定义的必需枚举验证器,如下所示。    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);        }   }然后你可以使用它,如下所示:public class AddressPostViewModel{    [JsonProperty("addressType")]    [RequiredEnumField(ErrorMessage = "Address type is required.")]    public AddressType AddressType { get; set; }}选项 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);    }}使用这个 jsonConverter 而不是默认的 StringEnumConverter 如下所示[JsonConverter(typeof(CustomStringToEnumConverter))]public enum AddressType{}

喵喵时光机

我想出了一个满足我要求的解决方案,尽管代码让我有点畏缩。我将属性保留在视图模型中的[Required]属性上。AddressType令人畏惧的部分是我必须制作该财产nullable:public class AddressPostViewModel{    [JsonProperty("addressType")]    [Required(ErrorMessage = "Address type is required.")]    public AddressType? AddressType { get; set; }}在AttributeType枚举本身上,我用@Manoj Choudhari 建议StringEnumConverter的自定义替换了属性:JsonConverter[JsonConverter(typeof(CustomStringToEnumConverter))]public enum AddressType{    [EnumMember(Value = "Dropship")]    Dropship,    [EnumMember(Value = "Shipping")]    Shipping}这是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;        }    }}CustomStringToEnumConverter可以处理空字符串、空值和无效字符串。如果遇到无效的枚举值,它会返回null,然后在发生必填字段验证(魔术)时捕获该值,并RequiredAttribute在 JSON 响应中显示错误消息。虽然我不喜欢将类型设为可为空,但如果请求 JSON 中的值错误AttributeType,我的 API 使用者将看到一致的验证消息。AttributeType

慕的地6264312

我认为没有开箱即用的数据注释来验证枚举值。不过,您可以从 required 属性派生:using System;using System.ComponentModel.DataAnnotations;    public class RequiredEnumAttribute : RequiredAttribute    {        public override bool IsValid(object value)        {            if (value == null) return false;            var type = value.GetType();            return type.IsEnum && Enum.IsDefined(type, value);        }}该Enum.IsDefined方法正在检查给定value的枚举中是否存在给定type。用法:[RequiredEnum(ErrorMessage = "Your error message.")]public YourEnum EnumProperty { get; set; }见这篇文章。

潇潇雨雨

(请参阅此处的完整文章:https ://mtarleton.medium.com/enum-as-required-field-in-asp-net-core-webapi-a79b697ef270 )这里面临的问题是将正文转换为 JSON 和验证模型验证的操作顺序。首先,.NET 将正文反序列化为带有默认值的 JSON 。这意味着如果您为不可为空的 ENUM 传入一个空值,则会为其设置默认值(通常是 ENUM 中的第一项)。同样的事情也会发生在原始人身上。[JsonProperty(Required = Required.Always)]
打开App,查看更多内容
随时随地看视频慕课网APP