C# 模型枚举字段的ASP.NET自定义错误消息

C# 模型枚举字段的ASP.NET自定义错误消息,c#,enums,asp.net-core-2.1,validationattribute,ivalidatableobject,C#,Enums,Asp.net Core 2.1,Validationattribute,Ivalidatableobject,我正在开发一个基于EntityFrameworkCore的网站,目标是ASP.NET Core 2.1。我想为模型中的枚举字段指定一条错误消息,如下所示: [RequiredErrorMessage=从列表中选择一项。] public MyEnum MyEnum{get;set;} 但是,仍会生成股票消息:值“0”无效。问题似乎是在对我的任何代码求值之前验证了枚举类型。这里介绍的两种方法,或者创建一个从ValidationAttribute继承的类,或者让模型从IValidatableObjec

我正在开发一个基于EntityFrameworkCore的网站,目标是ASP.NET Core 2.1。我想为模型中的枚举字段指定一条错误消息,如下所示:

[RequiredErrorMessage=从列表中选择一项。] public MyEnum MyEnum{get;set;} 但是,仍会生成股票消息:值“0”无效。问题似乎是在对我的任何代码求值之前验证了枚举类型。这里介绍的两种方法,或者创建一个从ValidationAttribute继承的类,或者让模型从IValidatableObject继承,都会遇到这种问题

我找到了一个解决方法:将字段声明为int,然后使用自定义验证属性:

[EnumCheckTypeOfMyNum,ErrorMessage=从列表中选择一项。] 公共int MyEnum{get;set;} …然后从ValidationAttribute中创建子类:

密封的公共类枚举检查:ValidationAttribute { 只读类型t; 公共枚举类型t { t=t; } 公共覆盖布尔IsValidobject值 { 返回Enum.IsDefinedt_u2;,值; } } 这种方法有一些缺点,因为现在我需要在许多地方将字段强制转换为枚举类型

是否有方法为枚举字段类型提供错误消息

更新

下面的示例不再使用ValidationAttribute中的EnumCheck子类,而是@péterCsajtai提到的EnumDataType:

模型

控制器

看法

以及form post之后的输出:


我认为您正在搜索EnumDataTypeAttribute:

在您最初的情况下,[RequiredErrorMessage=从列表中选择一项。]您正在设置如果缺少MyEnum将显示的消息。但与所有ValueType一样,它永远不会丢失,因此它永远不会触发验证。解决此问题的方法是使用可为null的ValueType

由于模型绑定失败,您的第二项工作仍然不起作用–空白值可以转换为一天吗?不,不能。在验证生效之前生效

类型验证的前提是您要验证该类型的实例。Aspnetcore将表单post转换为类型化值的方式是modelbinding。如果发布的值不能进行模型绑定(例如,如果将boo发布到声明为int的属性,或将空字符串发布到Enum),则验证将永远不会开始。而是显示modelbinding错误

简单的解决办法是

使用可为空的枚举,天?因此,modelbinding一个blank成功地将blank解析为null。 使用[Required]使空值无法通过验证。 结论:将您的表格更改为:

public class Form
{
    [Required(ErrorMessage = "Select an item from the list.")]
    public Day? Day { get; set; }
}
然后它就会像你期望的那样工作

参考:


注意:与其他ValidationAttribute不同,虽然继承自ValidationAttribute,但没有给出使用它进行验证的示例。相反,示例是将其用于元数据。

Enum是一个int。可能0是您的问题。您是否尝试将第一个枚举设置为1?@Manta是的,我尝试过。事实上,这就是我第一次注意到这个问题的原因。MyEnum由一个选择框填充,该框最初只包含枚举中的每个元素。然后,我决定在列表顶部添加一个“Choose One…”选项,并将其值设置为0。有点像是在搜索此选项:这很有用,它似乎与EnumCheck属性类的功能完全相同,因此我可以删除它。但是,如果我将该字段声明为public MyEnum MyEnum{get;set;},那么我会得到一个结果,即值“0”是无效消息,而不是指定的ErrorMessage。我仍然必须将字段声明为int。这很奇怪,我在我的示例项目中得到了正确的验证消息,您如何准确地进行验证?正如您所拥有的那样。我已经做了一个新的解决方案/项目,作为一个最小的例子,结果是一样的。也许我需要另一种显示错误的方法?我已经尝试过这两种方法:@Html.ValidationMessageForm=>m.MyEnum,我认为这个计划永远不会奏效。如果无法将发布的值转换为枚举,则永远不会访问ValidationAttribute。错误发生在模型绑定的前一个阶段。如果发布的值可以转换为枚举,则验证始终通过!无论如何,此ValidationAttribute永远不会返回失败。
namespace web.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Save(Form model)
        {
            if(!ModelState.IsValid)
            {
                return View("Index");
            }

            return View("Index", model);
        }
    }
}
<form asp-controller="Home">
    <div asp-validation-summary="All" class="text-danger"></div>
    <fieldset>
        <label asp-for="@Model.Day"></label>
        <select asp-for="@Model.Day" asp-items="Html.GetEnumSelectList<Day>()">
            <option value="">Select...</option>
        </select>
        @Html.ValidationMessageFor(m => m.Day)
        <span asp-validation-for="@Model.Day" class="text-danger"></span>
    </fieldset>
    <fieldset>
        <input type="submit" asp-action="Save" />
    </fieldset>
</form>
[EnumDataType(typeof(MyEnum), ErrorMessage = "Select an item form the list.")]
public MyEnum MyEnum { get; set; }
public class Form
{
    [Required(ErrorMessage = "Select an item from the list.")]
    public Day? Day { get; set; }
}