Mat*_*zer 5 c# enums validationattribute ivalidatableobject asp.net-core-2.1
我正在开发一个基于 EntityFrameworkCore 并针对 ASP.NET Core 2.1 的网站。我想为模型中的枚举字段指定错误消息,如下所示:
\n\n[Required(ErrorMessage = "Select an item from the list.")]\npublic MyEnum MyEnum { get; set; }\n
Run Code Online (Sandbox Code Playgroud)\n\n但是,仍然生成库存消息:The value \'0\' is invalid
。问题似乎是在评估我的任何代码之前验证枚举类型。这里介绍的两种方法(https://www.codeproject.com/Articles/1204077/ASP-NET-Core-MVC-Model-Validation),要么创建一个继承自 ValidationAttribute 的类,要么让模型继承自 IValidatableObject受此之苦。
我找到了一个解决方法:将字段声明为 int,然后使用自定义验证属性:
\n\n[EnumCheck(typeof(MyEnum), ErrorMessage = "Select an item form the list.")]\npublic int MyEnum { get; set; }\n
Run Code Online (Sandbox Code Playgroud)\n\n...然后从 ValidationAttribute 继承子类:
\n\nsealed public class EnumCheck : ValidationAttribute\n{\n readonly Type t_;\n\n public EnumCheck(Type t)\n {\n t_ = t;\n }\n\n public override bool IsValid(object value)\n {\n return Enum.IsDefined(t_, value);\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n这种方法有一些缺点,因为现在我需要在许多使用它的地方将字段转换为 Enum 类型。
\n\n有没有办法为 Enum 字段类型提供 ErrorMessage?
\n\n更新
\n\n以下是一个最小的示例(不再使用 ValidationAttribute 中的 EnumCheck 子类,而是使用 @P\xc3\xa9terCsajtai 提到的 EnumDataType):
\n\n型号\n
\n\nnamespace web.Models\n{\n public enum Day\n {\n Sunday = 1,\n Monday,\n Tuesday,\n Wednesday,\n Thursday,\n Friday,\n Saturday\n }\n\n public class Form\n {\n [EnumDataType(typeof(Day), ErrorMessage = "Select an item from the list.")]\n public Day Day { get; set; }\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n控制器\n
\n\nnamespace web.Controllers\n{\n public class HomeController : Controller\n {\n public IActionResult Index()\n {\n return View();\n }\n\n public IActionResult Save(Form model)\n {\n if(!ModelState.IsValid)\n {\n return View("Index");\n }\n\n return View("Index", model);\n }\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n查看\n
\n\n<form asp-controller="Home">\n <div asp-validation-summary="All" class="text-danger"></div>\n <fieldset>\n <label asp-for="@Model.Day"></label>\n <select asp-for="@Model.Day" asp-items="Html.GetEnumSelectList<Day>()">\n <option value="">Select...</option>\n </select>\n @Html.ValidationMessageFor(m => m.Day)\n <span asp-validation-for="@Model.Day" class="text-danger"></span>\n </fieldset>\n <fieldset>\n <input type="submit" asp-action="Save" />\n </fieldset>\n</form>\n
Run Code Online (Sandbox Code Playgroud)\n\n以及表单发布后的输出:
\n\n\n在您原来的情况下,[Required(ErrorMessage = "Select an item from the list.")]
您正在设置消息丢失时显示的消息MyEnum
。但与所有 ValueType 一样,它永远不会丢失,因此它永远不会触发该验证。解决方案是可以为 null 的 ValueType。
您的第二次努力仍然不起作用,因为模型绑定失败 \xe2\x80\x93 “可以将空白值转换为 吗Day
?不,它不能。” 在您的验证开始之前就开始。
验证的前提Type
是您有一个instance
要Type
验证的。Aspnetcore 将表单帖子转换为键入的值的方式是模型绑定。如果发布的值不能是模型绑定的——例如,如果您将“boo”发布到声明为 an 的属性int
,或者将空字符串发布到 an——Enum
那么验证甚至永远不会开始。相反,会显示模型绑定错误。
简单的解决方案是
\nDay?
以便 模型绑定空白成功(空白解析为null
)。[Required()]
该null
值会使验证失败。结论:将您的表格更改为:
\npublic class Form\n{\n [Required(ErrorMessage = "Select an item from the list.")]\n public Day? Day { get; set; }\n}\n
Run Code Online (Sandbox Code Playgroud)\n然后它就会按照您的预期工作。
\n\n注意,与其他 不同ValidationAttributes
, 的文档EnumDataType
虽然继承自 ValidationAttribute,但没有给出使用它进行验证的示例。相反,该示例是将其用于元数据。