0

I have a business requirement to only show the first 5 errors in the @Html.ValidationSummary. I have created a ValidationSummaryLimited htmlhelper but I cannot figure out how to implement the excludePropertyErrors piece.

public static string ValidationSummaryLimited(this HtmlHelper helper, bool excludePropertyErrors = false, string message = "")
{
    const int maximumValidations = 5;

    if (helper.ViewData.ModelState.IsValid)
        return string.Empty;

    StringBuilder sb = new StringBuilder();

    if (!string.IsNullOrEmpty(message))
    {
        sb.AppendFormat("<span>{0}</span>{1}", helper.Encode(message), System.Environment.NewLine);
    }

    sb.AppendLine("<div class=\"validation-summary-errors\" data-valmsg-summary=\"true\">");
    sb.AppendLine("\t<ul>");

    int count = 0;
    foreach (var key in helper.ViewData.ModelState.Keys) 
    {
        foreach (var err in helper.ViewData.ModelState[key].Errors)
        {
            count++;
            sb.AppendFormat("\t\t<li>{0}</li>{1}", helper.Encode(err.ErrorMessage),System.Environment.NewLine);

            if (count >= RVConstants.MaximumValidationErrors)
            {
                sb.AppendFormat("\t\t<li>Maximum of {0} errors shown</li>{1}",
                    maximumValidations, 
                    System.Environment.NewLine);
                break;
            }
        }

        if (count >= maximumValidations)
            break;
    }

    return sb.ToString();
}
Greg Finzer
  • 6,714
  • 21
  • 80
  • 125
  • Check this out might be helpful http://stackoverflow.com/questions/14714290/how-to-display-only-one-error-message-using-html-validationsummary – David May 19 '16 at 21:03
  • I recommend you study the [source code](https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/Html/ValidationExtensions.cs) - there is a lot that you not taking into account. In particular, the following - `public static MvcHtmlString ValidationSummary(this HtmlHelper htmlHelper, bool excludePropertyErrors, string message, IDictionary htmlAttributes)` and `private static IEnumerable GetModelStateList(HtmlHelper htmlHelper, bool excludePropertyErrors)` - in your case, your will just want a `.Take(5)` applied to the result of the 2nd method. –  May 20 '16 at 01:38

1 Answers1

0

I ended up leveraging the existing validation summary. Here is what I came up with:

public static MvcHtmlString ValidationSummaryLimited(this HtmlHelper helper,
    bool excludePropertyErrors)
{
    MvcHtmlString result = helper.ValidationSummary(excludePropertyErrors);
    return LimitSummaryResults(result);
}

private static MvcHtmlString LimitSummaryResults(MvcHtmlString summary)
{
    if (summary == null || summary.ToString() == string.Empty)
        return summary;

    int maximumValidations = RVConstants.MaximumValidationErrors;

    Regex exp = new Regex(@"<li[^>]*>[^<]*</li>",RegexOptions.IgnoreCase);

    string htmlString = summary.ToHtmlString();
    MatchCollection matches = exp.Matches(htmlString);

    if (matches.Count > maximumValidations)
    {
        string header = htmlString.Substring(0, htmlString.IndexOf("<ul>",StringComparison.Ordinal) + "<ul>".Length);
        string footer = htmlString.Substring(htmlString.IndexOf("</ul>", StringComparison.Ordinal));

        StringBuilder sb = new StringBuilder(htmlString.Length);
        sb.Append(header);

        for (int i = 0; i < maximumValidations; i++)
        {
            sb.Append(matches[i].Value);
        }

        sb.AppendFormat("<li>Maximum of {0} errors shown</li>", maximumValidations);

        sb.Append(footer);

        string limited = sb.ToString();
        return new MvcHtmlString(limited);
    }

    return summary;
}
Greg Finzer
  • 6,714
  • 21
  • 80
  • 125