public static MvcHtmlString ValidationSummary(this HtmlHelper htmlHelper, bool excludePropertyErrors, string message, IDictionary <string, object> htmlAttributes) { if (htmlHelper == null) { throw new ArgumentNullException("htmlHelper"); } FormContext formContext = htmlHelper.ViewContext.GetFormContextForClientValidation(); if (htmlHelper.ViewData.ModelState.IsValid) { if (formContext == null) { // No client side validation return(null); } // TODO: This isn't really about unobtrusive; can we fix up non-unobtrusive to get rid of this, too? if (htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled && excludePropertyErrors) { // No client-side updates return(null); } } string messageSpan; if (!String.IsNullOrEmpty(message)) { TagBuilder spanTag = new TagBuilder("span"); spanTag.SetInnerText(message); messageSpan = spanTag.ToString(TagRenderMode.Normal) + Environment.NewLine; } else { messageSpan = null; } StringBuilder htmlSummary = new StringBuilder(); TagBuilder unorderedList = new TagBuilder("ul"); IEnumerable <ModelState> modelStates = GetModelStateList(htmlHelper, excludePropertyErrors); foreach (ModelState modelState in modelStates) { foreach (ModelError modelError in modelState.Errors) { string errorText = GetUserErrorMessageOrDefault(htmlHelper.ViewContext.HttpContext, modelError, null /* modelState */); if (!String.IsNullOrEmpty(errorText)) { TagBuilder listItem = new TagBuilder("li"); listItem.SetInnerText(errorText); htmlSummary.AppendLine(listItem.ToString(TagRenderMode.Normal)); } } } if (htmlSummary.Length == 0) { htmlSummary.AppendLine(HiddenListItem); } unorderedList.InnerHtml = htmlSummary.ToString(); TagBuilder divBuilder = new TagBuilder("div"); divBuilder.MergeAttributes(htmlAttributes); divBuilder.AddCssClass((htmlHelper.ViewData.ModelState.IsValid) ? HtmlHelper.ValidationSummaryValidCssClassName : HtmlHelper.ValidationSummaryCssClassName); divBuilder.InnerHtml = messageSpan + unorderedList.ToString(TagRenderMode.Normal); if (formContext != null) { if (htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled) { if (!excludePropertyErrors) { // Only put errors in the validation summary if they're supposed to be included there divBuilder.MergeAttribute("data-valmsg-summary", "true"); } } else { // client val summaries need an ID divBuilder.GenerateId("validationSummary"); formContext.ValidationSummaryId = divBuilder.Attributes["id"]; formContext.ReplaceValidationSummary = !excludePropertyErrors; } } return(divBuilder.ToMvcHtmlString(TagRenderMode.Normal)); }