Blazor Web App如何按模型Display Order属性排序验证错误消息
Blazor中让ValidationSummary按模型Display(Order)排序错误消息
问题场景
我在Blazor Web App组件中使用EditForm和ValidationSummary,功能正常但错误消息顺序不符合预期:自定义验证的错误会排在数据注解(比如[Required])的错误前面。比如留空FirstName且输入2个字符的MiddleName时,错误顺序是:
'Middle Name' must be at least 5 characters
'First Name' is required
但我希望按照模型中[Display(Order = XX)]属性定义的顺序展示错误消息(FirstName的Order=2,应该排在MiddleName的Order=3前面)。
模型代码:
public class ContactModel { [Display(Order = 1)] public int ContactID { get; set; } [Required] [Display(Order = 2)] public string FirstName { get; set; } [Display(Order = 3)] public string MiddleName { get; set; } [Required] [Display(Order = 4)] public string LastName { get; set; } }
自定义验证代码:
if (!String.IsNullOrEmpty(_model.MiddleName) && _model.MiddleName.Length < 5) { messageStore?.Add(() => _model.MiddleName, "Middle name must be at least 5 characters."); } _editContext.NotifyValidationStateChanged();
解决方案
默认的ValidationSummary不支持按模型属性顺序排序,需要自定义一个排序后的验证摘要组件:
1. 创建自定义SortedValidationSummary组件
新建SortedValidationSummary.razor文件,代码如下:
@inject EditContext EditContext @if (EditContext?.GetValidationMessages().Any() == true) { <div class="validation-summary-errors" role="alert"> <ul> @foreach (var message in GetSortedValidationMessages()) { <li>@message</li> } </ul> </div> } @code { private IEnumerable<string> GetSortedValidationMessages() { // 关联验证消息与对应字段 var fieldMessages = new List<(string Message, int Order)>(); var modelType = typeof(ContactModel); foreach (var fieldIdentifier in EditContext.GetFieldsWithValidationMessages()) { // 获取属性的DisplayOrder var property = modelType.GetProperty(fieldIdentifier.FieldName); var displayOrder = property?.GetCustomAttributes(typeof(DisplayAttribute), false) .Cast<DisplayAttribute>() .FirstOrDefault()?.Order ?? int.MaxValue; // 收集该字段的所有错误消息 foreach (var msg in EditContext.GetValidationMessages(fieldIdentifier)) { fieldMessages.Add((msg, displayOrder)); } } // 按DisplayOrder排序后返回消息 return fieldMessages.OrderBy(item => item.Order).Select(item => item.Message); } }
2. 替换原ValidationSummary
在你的Blazor组件中,把原来的<ValidationSummary />替换为自定义组件:
<EditForm Model="@_model" OnValidSubmit="@HandleValidSubmit"> <!-- 表单输入控件 --> <SortedValidationSummary /> <button type="submit">提交</button> </EditForm>
3. 通用化扩展(可选)
如果需要让组件支持任意模型,可以改成泛型组件:
@typeparam TModel @inject EditContext EditContext @if (EditContext?.GetValidationMessages().Any() == true) { <div class="validation-summary-errors" role="alert"> <ul> @foreach (var message in GetSortedValidationMessages()) { <li>@message</li> } </ul> </div> } @code { private IEnumerable<string> GetSortedValidationMessages() { var fieldMessages = new List<(string Message, int Order)>(); var modelType = typeof(TModel); foreach (var fieldIdentifier in EditContext.GetFieldsWithValidationMessages()) { var property = modelType.GetProperty(fieldIdentifier.FieldName); var displayOrder = property?.GetCustomAttributes(typeof(DisplayAttribute), false) .Cast<DisplayAttribute>() .FirstOrDefault()?.Order ?? int.MaxValue; foreach (var msg in EditContext.GetValidationMessages(fieldIdentifier)) { fieldMessages.Add((msg, displayOrder)); } } return fieldMessages.OrderBy(item => item.Order).Select(item => item.Message); } }
使用时指定模型类型:
<SortedValidationSummary TModel="ContactModel" />
这样修改后,错误消息就会严格按照模型中[Display(Order)]定义的顺序展示。
内容的提问来源于stack exchange,提问作者FirstByte
相关产品推荐
相关产品推荐

