ValidationMessage - 处理同一属性的多个错误

时间:2009-06-05 16:34:21

标签: asp.net-mvc

我在MVC中使用ValidationMessage控件。验证每个属性时,可能会显示多个错误消息,但ValidationMessage仅显示列表中的第一条错误消息。

以下是一个例子:

ModelState["Key"] = new ModelState();
ModelState["Key"].Errors.Add("Error 1");
ModelState["Key"].Errors.Add("Error 2");

并在html中我有:<%= Html.ValidationMessage("Key")%>

显示:"Error 1"

我希望在页面上看到"Error 1 Error 2"

的所有错误消息

知道该怎么做吗?

6 个答案:

答案 0 :(得分:6)

我有完全相同的问题,所以我为HtmlHelper创建了一个扩展方法,作为MVC ValidationMessage方法的替代。

这比ValidationSummary方法的好处是它显示每个字段的错误消息,因此您可以将它放在每个字段旁边(与ValidationMessage方法相同)。

public static string AllValidationMessage(this HtmlHelper helper, string modelName)
{
    StringBuilder builder = new StringBuilder();
    TagBuilder ulTag = new TagBuilder("ul");
    ulTag.AddCssClass("u-error-list");

    builder.Append(ulTag.ToString(TagRenderMode.StartTag));
    if (helper.ViewData.ModelState.ContainsKey(modelName) &&
        helper.ViewData.ModelState[modelName].Errors.Count > 0)
    {
        foreach (var err in helper.ViewData.ModelState[modelName].Errors)
        {
            TagBuilder liTag = new TagBuilder("li") { InnerHtml = HttpUtility.HtmlEncode(err.ErrorMessage) };
            liTag.AddCssClass("u-error-item");
            builder.Append(liTag.ToString());
        }
    }
    builder.Append(ulTag.ToString(TagRenderMode.EndTag));

    var msgSpan = helper.ValidationMessage(modelName, "{placeholder}");

    if (msgSpan == null)
        return string.Empty;

    return msgSpan.ToHtmlString().Replace("{placeholder}", builder.ToString());
}

public static string AllValidationMessageFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
    return HtmlHelperExtensions.AllValidationMessage(helper, ExpressionHelper.GetExpressionText(expression));
}

编辑:添加了AllValidationMessageFor方法
修改:在msgSpan上添加了空检查

答案 1 :(得分:2)

只需开箱即用的MVC,您就必须添加ValidationSummary:

<%= Html.ValidationSummary() %>

这将显示所有ModelErrors。

答案 2 :(得分:1)

根据此处和How to display multiple validation errors with @Html.ValidationMessageFor?中提供的解决方案,我为属性创建了自己的多行验证消息。它的行为有点像ValidationSummary,但可以在每个字段中使用。我使用它为模型的集合字段提供验证消息。这允许我为集合和仅集合提供摘要消息。

public static MvcHtmlString MultilineValidationMessageFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null)
{
    var propertyName = ExpressionHelper.GetExpressionText(expression);
    var modelState = htmlHelper.ViewData.ModelState;

    // If we have multiple (server-side) validation errors, collect and present them.
    if (modelState.ContainsKey(propertyName) && modelState[propertyName].Errors.Count > 1)
    {
        var msgs = new StringBuilder();
        foreach (ModelError error in modelState[propertyName].Errors)
        {
            msgs.AppendLine(error.ErrorMessage + "<br />");
        }

        // Return standard ValidationMessageFor, overriding the message with our concatenated list of messages.
        var msgSpan = htmlHelper.ValidationMessageFor(expression, "{0}", htmlAttributes as IDictionary<string, object> ?? htmlAttributes);
        var msgDiv = msgSpan.ToHtmlString().Replace("span", "div");

        return new MvcHtmlString(string.Format(msgDiv, msgs.ToString()));
    }

    // Revert to default behaviour.
    return htmlHelper.ValidationMessageFor(expression, null, htmlAttributes as IDictionary<string, object> ?? htmlAttributes);
}

答案 3 :(得分:1)

由于ModelState遵循错误的字典模式,最终我们需要将所有错误连接到单个ModelState键中:

   ModelState["Key"].Errors.Add("Error 1. " + "Error 2");

如果您使用IValidatableObject convention执行自定义验证,则可以将验证结果失败转换为ModelState条目,如下所示:

var resultsGroupedByMembers = validationResults
    .SelectMany(_ => _.MemberNames.Select(
         x => new {MemberName = x ?? "", 
                   Error = _.ErrorMessage}))
    .GroupBy(_ => _.MemberName);

foreach (var member in resultsGroupedByMembers)
{
    ModelState.AddModelError(
        member.Key,
        string.Join(". ", member.Select(_ => _.Error)));
}

需要交叉连接,注意每个验证结果可能有多个MemberName。未绑定的结果将被绑定到&#34;&#34;并且应该可用于ValidationSummary

答案 4 :(得分:1)

更直接的方法:

控制器:

ModelState.AddModelError("other", "error 1");
ModelState.AddModelError("other", "error 2");
ModelState.AddModelError("other", "error 3");

查看:

<ul>
    @foreach (var error in Html.ViewData.ModelState["other"].Errors)
    {
        <li>@error.ErrorMessage</li>
    }
</ul>

答案 5 :(得分:0)

同样在您的Controller Action中,您可以查看

ModelState.IsValid

如果为false,只需返回View,并填充ValidationSumary。