views:

474

answers:

3

Is there any reason why ValidationMessages would display in a different order than the order you added the model errors?

I can't really help much because I have no idea how Html.ValidationSummary works to output what it does. If there's anything I could add that would help diagnose the problem, please comment and I'll add it if I can.

+1  A: 

asp.net mvc is open source so you can see the code for ValidationSummary directly.

http://www.asp.net/mvc/download/

That said, I'm pretty sure ModelState is a dictionary. So if ValidationSummary is iterating over the key/values in the ModelState dictionary looking for errors the order is going to be random.


I downloaded the code at work. From ValidationSummary in MVC/Html/ValidationExtensions.cs:

foreach (ModelState modelState in htmlHelper.ViewData.ModelState.Values) {
    foreach (ModelError modelError in modelState.Errors) {
        // stuff to build a string with the error
    }
}

So it is iterating over the values in the dictionary. And from MSDN:

For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair(TKey, TValue) structure representing a value and its key. The order in which the items are returned is undefined.

and

The order of the values in the Dictionary(TKey, TValue).ValueCollection is unspecified

Emphasis mine.

eyston
I can peer into the modelstate and all the model errors are in the correct order - it's only when it's output that the order is different.
ajbeaven
added edit to answer.
eyston
+1  A: 

ValidationSummary is so simple, as pointed above it is just 2 loops (which you can do in 1 with LINQ's SelectMany) so you can make your own partial view for this and place it in master layout in 5 minutes.

And given that ValidationSummary will not display Exceptions put in ModelState, there's a good reason to do this, anyway.

If you want to have the same order as controls in your view, you can do 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>");
});

Well, this code is from my head so it's pseudo... but this is the idea. Basically you iterate over all elements with name attribute, and check ModelState for and error. To make this happen, your server-side code creates a client-side dictionary of errors.

A better one would be to write a HtmlHelper extension that basically does the same, but in C# code file so that it doesn't mess your view.

queen3
+1  A: 
<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>

This might be helpful..

Rajesh