ASP.NET 模型枚举字段的自定义错误消息
ASP.NET Custom ErrorMessage for Model Enum field
我正在开发一个基于 EntityFrameworkCore 并面向 ASP.NET Core 2.1 的网站。我想为我的模型中的枚举字段指定一条错误消息,如下所示:
[Required(ErrorMessage = "Select an item from the list.")]
public MyEnum MyEnum { get; set; }
但是,仍然生成股票消息:The value '0' is invalid
。问题似乎是在评估我的任何代码之前验证了 Enum 类型。这里介绍的两种方法 (https://www.codeproject.com/Articles/1204077/ASP-NET-Core-MVC-Model-Validation),要么创建一个从 ValidationAttribute 继承的 class,要么让模型从 IValidatableObject 继承,这两种方法都受此影响。
我找到了解决方法:将字段声明为 int,然后使用自定义验证属性:
[EnumCheck(typeof(MyEnum), ErrorMessage = "Select an item form the list.")]
public int MyEnum { get; set; }
...然后从 ValidationAttribute:
子class
sealed public class EnumCheck : ValidationAttribute
{
readonly Type t_;
public EnumCheck(Type t)
{
t_ = t;
}
public override bool IsValid(object value)
{
return Enum.IsDefined(t_, value);
}
}
这种方法有一些缺点,因为现在我需要在许多使用它的地方将字段转换为 Enum 类型。
有没有办法为枚举字段类型提供错误消息?
更新
以下是一个最小示例(不再使用 ValidationAttribute 中的 EnumCheck subclass,而是 @PéterCsajtai 提到的 EnumDataType):
型号
namespace web.Models
{
public enum Day
{
Sunday = 1,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
public class Form
{
[EnumDataType(typeof(Day), ErrorMessage = "Select an item from the list.")]
public Day Day { get; set; }
}
}
控制器
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>
表格post后的输出:
我认为您正在搜索 EnumDataTypeAttribute
:
[EnumDataType(typeof(MyEnum), ErrorMessage = "Select an item form the list.")]
public MyEnum MyEnum { get; set; }
在您原来的情况下,[Required(ErrorMessage = "Select an item from the list.")]
您正在设置 MyEnum
缺失时显示的消息。但与所有 ValueType 一样,它可以 永远不会 丢失,因此它永远不会触发该验证。解决方案是可以为 null 的 ValueType。
您的第二次尝试仍然无效,因为 模型绑定 失败 – “可以将空白值转换为 Day
吗?不,不能。”在您的 验证 开始之前开始。
Type
的验证假设您有一个 Type
的 instance
来验证。 Aspnetcore 将表单 post 转换为该类型值的方式是模型绑定。如果 posted 值不能被模型绑定——例如,如果你 post “boo” 声明为 int
的 属性 或空字符串到 Enum
- 然后 validation 甚至永远不会开始。而是显示 modelbinding 错误。
简单的解决方案是
- 使用 nullable enum,
Day?
以便 modelbinding 空白成功(空白解析为 null
).
- 使用
[Required()]
以便 null
值无法通过验证。
结论:将您的表格更改为:
public class Form
{
[Required(ErrorMessage = "Select an item from the list.")]
public Day? Day { get; set; }
}
然后它将如您所愿地工作。
参考:Model Validation in AspNet Core MVC
NB 与其他 ValidationAttributes
不同,documentation for EnumDataType
虽然继承自 ValidationAttribute,但没有给出使用它进行验证的示例。相反,示例是将它用于元数据。
定义您的模型:
public enum Day
{
None=0,
Sunday = 1,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
然后定义您的自定义验证属性:
sealed public class EnumCheck : ValidationAttribute
{
readonly Type t_;
public EnumCheck(Type t)
{
t_ = t;
}
public override bool IsValid(object value)
{
if (((int)value)==0)
{
return false;
}
return Enum.IsDefined(t_, value);
}
}
最后在您看来使用这个:
<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="0">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>
我正在开发一个基于 EntityFrameworkCore 并面向 ASP.NET Core 2.1 的网站。我想为我的模型中的枚举字段指定一条错误消息,如下所示:
[Required(ErrorMessage = "Select an item from the list.")]
public MyEnum MyEnum { get; set; }
但是,仍然生成股票消息:The value '0' is invalid
。问题似乎是在评估我的任何代码之前验证了 Enum 类型。这里介绍的两种方法 (https://www.codeproject.com/Articles/1204077/ASP-NET-Core-MVC-Model-Validation),要么创建一个从 ValidationAttribute 继承的 class,要么让模型从 IValidatableObject 继承,这两种方法都受此影响。
我找到了解决方法:将字段声明为 int,然后使用自定义验证属性:
[EnumCheck(typeof(MyEnum), ErrorMessage = "Select an item form the list.")]
public int MyEnum { get; set; }
...然后从 ValidationAttribute:
子classsealed public class EnumCheck : ValidationAttribute
{
readonly Type t_;
public EnumCheck(Type t)
{
t_ = t;
}
public override bool IsValid(object value)
{
return Enum.IsDefined(t_, value);
}
}
这种方法有一些缺点,因为现在我需要在许多使用它的地方将字段转换为 Enum 类型。
有没有办法为枚举字段类型提供错误消息?
更新
以下是一个最小示例(不再使用 ValidationAttribute 中的 EnumCheck subclass,而是 @PéterCsajtai 提到的 EnumDataType):
型号
namespace web.Models
{
public enum Day
{
Sunday = 1,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
public class Form
{
[EnumDataType(typeof(Day), ErrorMessage = "Select an item from the list.")]
public Day Day { get; set; }
}
}
控制器
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>
表格post后的输出:
我认为您正在搜索 EnumDataTypeAttribute
:
[EnumDataType(typeof(MyEnum), ErrorMessage = "Select an item form the list.")]
public MyEnum MyEnum { get; set; }
在您原来的情况下,
[Required(ErrorMessage = "Select an item from the list.")]
您正在设置MyEnum
缺失时显示的消息。但与所有 ValueType 一样,它可以 永远不会 丢失,因此它永远不会触发该验证。解决方案是可以为 null 的 ValueType。您的第二次尝试仍然无效,因为 模型绑定 失败 – “可以将空白值转换为
Day
吗?不,不能。”在您的 验证 开始之前开始。
Type
的验证假设您有一个 Type
的 instance
来验证。 Aspnetcore 将表单 post 转换为该类型值的方式是模型绑定。如果 posted 值不能被模型绑定——例如,如果你 post “boo” 声明为 int
的 属性 或空字符串到 Enum
- 然后 validation 甚至永远不会开始。而是显示 modelbinding 错误。
简单的解决方案是
- 使用 nullable enum,
Day?
以便 modelbinding 空白成功(空白解析为null
). - 使用
[Required()]
以便null
值无法通过验证。
结论:将您的表格更改为:
public class Form
{
[Required(ErrorMessage = "Select an item from the list.")]
public Day? Day { get; set; }
}
然后它将如您所愿地工作。
参考:Model Validation in AspNet Core MVC
NB 与其他 ValidationAttributes
不同,documentation for EnumDataType
虽然继承自 ValidationAttribute,但没有给出使用它进行验证的示例。相反,示例是将它用于元数据。
定义您的模型:
public enum Day
{
None=0,
Sunday = 1,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
然后定义您的自定义验证属性:
sealed public class EnumCheck : ValidationAttribute
{
readonly Type t_;
public EnumCheck(Type t)
{
t_ = t;
}
public override bool IsValid(object value)
{
if (((int)value)==0)
{
return false;
}
return Enum.IsDefined(t_, value);
}
}
最后在您看来使用这个:
<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="0">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>