views:

144

answers:

1

Since the validation summary just displays the modelstate errors in a html list, does this mean that I can have only one validation summary? Or is there a way I can associate some kind of context to say that these modelstate errors show up on this summary and these go to the other?

+1  A: 

That will require you to write your own Validation Summary, either a HTML helper or Partial View. That will look something like this if you take the partial view way.

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>

<%
    string prefix = ViewData["prefix"].ToString();
    var l = ViewData.ModelState.Where(e => e.Value.Errors.Count != 0 && e.Key.Contains(prefix)).ToList();
    if (l.Count() > 0)
    {
            Response.Write("<div>");
            Response.Write("<span>Please fix fields marked with an asteristk</span>");
            Response.Write("<ul>");
            foreach (KeyValuePair<string, ModelState> keyValuePair in l)
            {
                foreach (ModelError modelError in keyValuePair.Value.Errors)
                {
                %>
                <li><%= Html.Encode(modelError.ErrorMessage)%></li>
                <%
    }
            } Response.Write("</ul>");
            Response.Write("</div>");
    }
    %>

I Assume that you will pass through ViewData some kind of identification (prefix) to your summary, so it know which errors to display on each Summary.

And it will be used like a normal partial View:

<% ViewData["prefix"] = "YOUR_PREFIX_HERE"; %>
<% Html.RenderPartial("CustomValidationSummary"); %>

PD: you can take this same logic and implement a HTML Helper instead, to make it smoother.

EDIT: added HTML Helper Implementation.

public static class CustomValidationSummary
    {
        public static string ValidationSummaryFor(this HtmlHelper htmlHelper, string message, string prefix, IDictionary<string, object> htmlAttributes)
        {
            if (htmlHelper.ViewData.ModelState.IsValid)
            {
                return null;
            }

            var l = htmlHelper.ViewData.ModelState.Where(e => e.Value.Errors.Count != 0 && e.Key.StartsWith(prefix)).ToList();

            // Nothing to do if there aren't any errors
            if (l.Count() == 0)
            {
                return null;
            }

            string messageSpan;
            if (!String.IsNullOrEmpty(message))
            {
                TagBuilder spanTag = new TagBuilder("span");
                spanTag.MergeAttributes(htmlAttributes);
                spanTag.MergeAttribute("class", HtmlHelper.ValidationSummaryCssClassName);
                spanTag.SetInnerText(message);
                messageSpan = spanTag.ToString(TagRenderMode.Normal) + Environment.NewLine;
            }
            else
            {
                messageSpan = null;
            }

            StringBuilder htmlSummary = new StringBuilder();
            TagBuilder unorderedList = new TagBuilder("ul");
            unorderedList.MergeAttributes(htmlAttributes);
            unorderedList.MergeAttribute("class", HtmlHelper.ValidationSummaryCssClassName);

            foreach (KeyValuePair<string, ModelState> keyValuePair in l)
            {
                foreach (ModelError modelError in keyValuePair.Value.Errors)
                {
                    var errorText = modelError.ErrorMessage;
                    if (!String.IsNullOrEmpty(errorText))
                    {
                        TagBuilder listItem = new TagBuilder("li");
                        listItem.SetInnerText(errorText);
                        htmlSummary.AppendLine(listItem.ToString(TagRenderMode.Normal));
                    }
                }
            }

            unorderedList.InnerHtml = htmlSummary.ToString();

            return messageSpan + unorderedList.ToString(TagRenderMode.Normal);
        }

    }

And to use it:

<% = Html.ValidationSummaryFor("Please fix fields marked with an asteristk","prefix",null) %>
Omar
I would make it a helper tho, so you can pass the prefix without having the 2 lines of code and using viewdata. good answer.
cottsak
Yep that will be the best way to go, it would be nice if you can share the helper with the community, and share me some credits =P, let me know if you do. Just like a note i think that "Key.Contains(prefix)" should be replaced with "Key.StartsWith(prefix)", i will edit the post with that change...
Omar