【问题标题】:In ASP.NET MVC, how to validate an integer property for an enumeration range在 ASP.NET MVC 中,如何验证枚举范围的整数属性
【发布时间】:2021-01-25 16:04:12
【问题描述】:

我正在 MVC 中创建一个 Web API。在我的 ViewModel-Objects 中,我想为整数输入创建验证,这些验证稍后会在过程中映射到一些枚举。

注意:由于项目范围之外的限制,我无法将视图模型的类型更改为实际的枚举。

这是我所拥有的:

[ClientValidation]
public class ContactDataObject {
    [Range(1,3)] //fixed range, bad
    public int? SalutationCd { get; set; }
}

我也可以

    [Range(/*min*/(int)Salutation.Mr, /*max*/(int)Salutation.LadiesAndGentlemen)]

这很好用,我们现在有 3 种称呼方式。但是,由于我已经知道这稍后会映射到枚举,所以我想做这样的事情,请参阅 [EnumDataTypeAttribute Class][1]。

[ClientValidation]
public class ContactDataObject {
    [EnumDataType(typeof(Salutation))] //gives mapping error
    public int? SalutationCd { get; set; }
}

但是,这会导致映射错误。

我想要一个属性,它只验证我的整数是否在给定枚举的值内。 如何验证枚举的(整数)

[1]:https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.enumdatatypeattribute?view=net-5.0):

【问题讨论】:

  • 我会写自己的 ValidationAttribute 来检查值是否可以转换为特定的枚举类型
  • 尝试使用Enum.GetNames(typeof(MyEnum)).Length获取枚举类型的长度
  • @KrishnaChaitanya 如果枚举使用显式值声明并且有间隙可能会失败
  • @KrishnaChaitanya 给定范围表达式的值必须是常量,因此这种动态方法不起作用
  • Length 给出枚举中元素的数量,而不管枚举中的间隙如何

标签: c# validation asp.net-mvc-5


【解决方案1】:

您可以尝试使用自定义验证:

public class EnumValueValidationAttribute : ValidationAttribute {
    private readonly Type _enumType;

    public EnumValueValidationAttribute(Type type) {
        _enumType = type;
    }

    public override bool IsValid(object value) {
        return value != null && Enum.IsDefined(_enumType, value); //null is not considered valid
    }
}

然后像这样使用它:

    [EnumValueValidation(typeof(Salutation))]
    public int? SalutationCd { get; set; }

【讨论】:

  • 根据 Franz 的评论,您不能这样做。枚举可以定义为 1、2、4、8。您只需检查长度,假设枚举始终为 0,1,2,3,... 您需要检查所检查的值是否实际上是枚举的值。不仅仅是长度检查
  • @Fran 是对的,但这种方法似乎普遍有效。我想我应该枚举要检查的枚举,而不仅仅是尝试获取长度,我猜?
  • 据我了解,lenght 给出了枚举长度,而不管枚举中的间隙如何。让我在我的机器上试一试,我会回来的。
  • @KrishnaChaitanya 我想你应该看看stackoverflow.com/a/2674751/79485。你会合并它,然后它看起来像一个有效的答案吗?
  • @KrishnaChaitanya 我添加了与您的非常相似的实际代码,包括类型和使用示例。如果没有人在 24 小时内提出更好的解决方案,我将接受这个答案
【解决方案2】:

此类允许您将列中的基础值映射到相应的枚举常量名称。这使您可以定义一个包含与数据库值对应的描述性值的枚举,然后在显示数据时使用枚举常量名称而不是数据库值。

[EnumDataType(typeof(ReorderLevel))]  
public object SalutationCd { get; set; }  

【讨论】:

  • 是的,我已经看到了(查看我的链接),但不幸的是它不适用于整数属性。
【解决方案3】:
public class EnumValidation : ValidationAttribute
{
    private readonly Type type;

    public EnumValidation(Type type)
    {
        this.type = type;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        string message = FormatErrorMessage(validationContext.DisplayName);

        if (value == null)
            return ValidationResult.Success;

        try
        {
            if (!Enum.IsDefined(type, (int)value))
                return new ValidationResult(message);
        }
        catch (Exception ex)
        {
            return new ValidationResult(message);
        }

        return ValidationResult.Success;
    }
}

[EnumValidation(type:typeof(MemberTypeEnum), ErrorMessageResourceType = typeof(Message), ErrorMessageResourceName = "ERR_Invalid")]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多