在 ValidationSummary 中,为什么消息显示的顺序与您将错误添加到 ModelState 的顺序不同,我该如何解决这个问题?
5 回答
<ul class="validation-summary-errors">
<%
foreach (ModelState modelState in (ViewContext.ViewData.ModelState.Values)){
foreach (ModelError modelError in modelState.Errors) {
// stuff to build a string with the error
%>
<li><%=modelError.ErrorMessage %></li>
<%
}
}
%>
</ul>
这可能会有所帮助..
我遇到了这个问题,为了快速解决它,我像上面一样重新创建了验证摘要,并使用 ViewBag 通过引用有序字段名称数组以正确的顺序存储错误。不是特别好,但我当时能想到的最快的事情。剃刀/MVC3。
控制器代码:
List<string> fieldOrder = new List<string>(new string[] {
"Firstname", "Surname", "Telephone", "Mobile", "EmailAddress", "AddressLine1", "AddressLine2", "TownCity", "County" })
.Select(f => f.ToLower()).ToList();
ViewBag.SortedErrors = ModelState
.Select(m => new { Order = fieldOrder.IndexOf(m.Key.ToLower()), Error = m.Value})
.OrderBy(m => m.Order)
.SelectMany(m => m.Error.Errors.Select(e => e.ErrorMessage))
.ToArray();
然后在视图中:
@if (!ViewData.ModelState.IsValid)
{
<div class="validation-summary-errors">
<ul>
@foreach (string sortedError in ViewBag.SortedErrors)
{
<li>@sortedError</li>
}
</ul>
</div>
}
asp.net mvc 是开源的,因此您可以直接查看 ValidationSummary 的代码。
http://www.asp.net/mvc/download/
也就是说,我很确定 ModelState 是一本字典。因此,如果 ValidationSummary 遍历 ModelState 字典中的键/值以查找错误,则顺序将是随机的。
我在工作时下载了代码。来自 MVC/Html/ValidationExtensions.cs 中的 ValidationSummary:
foreach (ModelState modelState in htmlHelper.ViewData.ModelState.Values) {
foreach (ModelError modelError in modelState.Errors) {
// stuff to build a string with the error
}
}
所以它正在迭代字典中的值。并来自 MSDN:
出于枚举的目的,字典中的每个项目都被视为表示值及其键的 KeyValuePair(TKey, TValue) 结构。返回项目的顺序未定义。
和
Dictionary(TKey, TValue).ValueCollection 中值的顺序未指定
强调我的。
ValidationSummary 非常简单,正如上面所指出的,它只是 2 个循环(您可以使用 LINQ 的 SelectMany 在 1 中完成),因此您可以为此制作自己的部分视图并在 5 分钟内将其放置在主布局中。
鉴于 ValidationSummary 不会显示放在 ModelState 中的异常,无论如何,这样做是有充分理由的。
如果您希望与视图中的控件具有相同的顺序,可以使用 jQuery:
var list = {};
<% foreach (var error in ModelState)
{%>
list['<%=error.Key%>'] = '<%=error.Value.Message%>';
<%}%>
$(*[name]).each(function(i,o){
isError = list.indexOf(o.name) >= 0;
if (isError)
$(".validationSummary").append("<li>" + list[o.name] + "</li>");
});
好吧,这段代码来自我的脑海,所以它是伪的......但这就是想法。基本上,您遍历具有 name 属性的所有元素,并检查 ModelState 是否有错误。为了实现这一点,您的服务器端代码会创建一个客户端错误字典。
一个更好的方法是编写一个基本相同的 HtmlHelper 扩展,但是在 C# 代码文件中,这样它就不会弄乱你的视图。
除了以前的答案之外,您还可以使用FluentValidation框架而不是 Data Annotations。如果要避免ModelState
手动使用和创建验证器,则ValidationResult
对象将以相同的顺序包含错误,因为在验证器构造函数中添加了相应的规则。
此外,如果启用了客户端验证 - 错误消息的顺序与相应输入的顺序相同,这些输入由生成的HtmlHelper
(可能对于数据注释生成的输入应该具有相同的行为)。
更多信息请看这里。