Geeks With Blogs
MightyZot

The Html.ValidationSummary helper writes a div with a list of general errors added to the model state while a request is being serviced. There is generally one form per view or partial view, I think, so often there is only one call to Html.ValidationSummary in the page resulting from the assembly of your views. And, consequently, there is no problem with the markup that Html.ValidationSummary spits out as a result. What if you want to put multiple forms in one view? Even if you create a view model that’s an aggregate of the view models for each form, the error validation summary is going to contain errors from both forms. Check out this screen shot, which shows a page with multiple forms. Notice how the error validation summary shows up twice. Grrr! Errors for the login form also show up in the registration form.

image

Luckily, there is an easy way around this. Pull the errors out of the model state and separate them for each form. You’ll need to identify the appropriate form by setting the key when you make calls to ModelState.AddModelError. Assume in my example that errors for the login form are added to model state using the “LoginForm” key. And, likewise, assume that errors for the registration form are added to model state using the “RegistrationForm” key. An example of that might look like this…

// If we got this far, something failed, redisplay form
ModelState.AddModelError("LoginForm", "User name or password is not right...");
return View(model);

Over in the code for your View, you can pull each form’s errors from the model state using lambda expressions that look like these…

var LoginFormErrors = ViewData.ModelState.Where(ms => ms.Key == "LoginForm");
var RegistrationFormErrors = ViewData.ModelState.Where(ms => ms.Key == "RegistrationForm");

Now that you have two collections containing errors, you can display only the errors specific to each form. I’m doing that in my code by removing the calls to Html.ValidationSummary and replacing them with enumerators that look like this…

if(LoginFormErrors.Count() > 0)
{
<div class="cdt-error-list">
    <ul>
    @foreach (var entry in LoginFormErrors)
    {
        foreach (var error in entry.Value.Errors)
        {
            <li>@error.ErrorMessage</li>
        }
    }
    </ul>
</div>
}

…and for the registration form, the code looks like this…

@if(RegistrationFormErrors.Count() > 0)
{
<div class="cdt-error-list">
    <ul>
    @foreach (var entry in RegistrationFormErrors)
    {
        foreach (var error in entry.Value.Errors)
        {
            <li>@error.ErrorMessage</li>
        }
    }
    </ul>
</div>
}

The result is a nice clean separation of the list of errors that are specific to each form. And, this is important because each form is submitted separately in my case, so both forms don’t generate errors in the same context. As you’ll see in the screen shot below, errors added to the model state when the login form is submitted do not show up in the registration form’s validation summary.

image

Posted on Monday, November 11, 2013 4:43 PM C# Tips and Tricks , Web , ASP.NET , MVC | Back to top


Comments on this post: Html.ValidationSummary and Multiple Forms

# re: Html.ValidationSummary and Multiple Forms
Requesting Gravatar...
Hi,

Nice post,

I'm currently dealing with a similar scenario and's it's not easy as pie when you do that for the first time...

How do you deal with errors that are thrown by the model's dataannotations ?

If you have some required properties in your model, how do you display them ?
Left by Sam on Nov 12, 2013 2:40 AM

# re: Html.ValidationSummary and Multiple Forms
Requesting Gravatar...
Hey Sam, great question. The model errors that occur because of data annotations are added to the ModelState in the same manner, except they are given keys indicating the model and the property (control). If you provide a view model with properties aggregating the view models for each of the forms independently, then MVC will separate them for you.

My view model originally had a base class with the properties for one form and then a derived view model class with properties for registration. Even though I'm still using that inheritance, I ended up adding that third model so that MVC would know which property values go with which forms.

But, you could separate them manually by pulling them from model state, like I have shown here. In my opinion, it's not worth the trouble.
Left by Markus Pope on Nov 12, 2013 12:20 PM

# re: Html.ValidationSummary and Multiple Forms
Requesting Gravatar...
Thanks for this blog post! Helped me a bunch right now.
Left by Henry on Sep 08, 2014 12:13 PM

# re: Html.ValidationSummary and Multiple Forms
Requesting Gravatar...
Very good one. Thanks!
Left by ZikO on Dec 16, 2014 3:42 AM

Your comment:
 (will show your gravatar)


Copyright © MightyZot | Powered by: GeeksWithBlogs.net