为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
慕哥6287543 2022-07-23 16:36:54
[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]如果有人不包含枚举的有效值,是否有办法确保返回属性的错误消息?
查看完整描述

4 回答

?
开心每一天1111

TA贡献1836条经验 获得超13个赞

选项 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

{

}


查看完整回答
反对 回复 2022-07-23
?
喵喵时光机

TA贡献1846条经验 获得超7个赞

我想出了一个满足我要求的解决方案,尽管代码让我有点畏缩。


我将属性保留在视图模型中的[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


查看完整回答
反对 回复 2022-07-23
?
慕的地6264312

TA贡献1817条经验 获得超6个赞

我认为没有开箱即用的数据注释来验证枚举值。


不过,您可以从 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; }

见这篇文章。


查看完整回答
反对 回复 2022-07-23
?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

(请参阅此处的完整文章:https ://mtarleton.medium.com/enum-as-required-field-in-asp-net-core-webapi-a79b697ef270 )

这里面临的问题是将正文转换为 JSON 和验证模型验证的操作顺序。

首先,.NET 将正文反序列化为带有默认值的 JSON 。这意味着如果您为不可为空的 ENUM 传入一个空值,则会为其设置默认值(通常是 ENUM 中的第一项)。同样的事情也会发生在原始人身上。

[JsonProperty(Required = Required.Always)]


查看完整回答
反对 回复 2022-07-23
  • 4 回答
  • 0 关注
  • 306 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号