MVC ModelState.AddError versus ModelStateDictonary

So everyone using ASP.NET MVC at one point or another has made a form I’m sure. Within that form, there is bound to be some business logic that in some way shape or form restricts what data is required, the data type allowed, cross field validation etc… In doing this, many people use the built in Data Attributes that come with the MVC framework which in most cases inserts unobtrusive JavaScript into your form fields so the browser can validate the users input immediately before the data is sent to the server. You can also write your own JavaScript to interact with the DOM. Both of these techniques are called client side validation.

Server Side Validation

On the other hand, there are many things that either cannot be done on the client side or are just too difficult to code in a timely fashion in JavaScript. In these cases you can do your validation in the C# code. This is also known as server side validation. Server Side validation occurs on the “server” upon post-back from the browser. At this point, all client side validation has occurred.

To do server side validation, there are several choices. One choice is to override the Validate method in your View Model. This method gets called during model-bind when the form is posted. I wrote an article on how to use this method properly here.

ModelState uses

Another way is to do some fancy footwork with the ModelState object. This object contains as you might guess, the state of the model that has been bound. The validate method actually leverages this object, but as anything else, when you work with an object directly, you have more control over it’s function.

ModelState.AddError()

The AddError method off of the ModelState is often used when you want to highlight a specific field as an error based on some calculation or cross-field validation. An example of this, would be something like the following:

if(model.prop1 != model.prop2)
{
    ModelState.AddError("prop3","Unable to have prop 1 and 2 as different values")
}  

Now, when you push the View, the prop3 field would be highlighted with the error above showing on top of the field.

ModelState.ModelStateDictionary

What I really like about the ModelStateDictionary is that it is much easier to continue to place business logic in the ViewModel where it really belongs and not in the Controller. This dictionary keeps a record of all the key values of the bound properties, the error they should return and whether or not they are in an error state based on an IsValid property. This property returns a Boolean. You can add to the dictionary of error properties by calling the AddModelError. This method is identical to the AddError method except that it is in the dictionary and not the Model itself.

An example of how you would implement this is shown below with a static method that would be placed in the ViewModel for Person.

        public static ModelStateDictionary ValidateProperties(Person model)
        {
            var dictionary = new ModelStateDictionary();
            if (model.Age > 18)
            {
                dictionary.AddModelError("Age", "You're an adult and cannot use this form.");
            }
          
            return dictionary;
        }

Now, to use this model in the Controller, you would call it like this:

ModelState.Merge(Person.ValidateProperties(personModel));

 

The ModelState.Merge takes in a dictionary and will merge it’s data with any other errors. You can then do the normal check for a valid model like so:

if(!ModelState.IsValid)
{
return View();
}
 

Conclusion

In conclusion, using the dictionary technique can make things much cleaner and does a better job of SoC, but any of the above techniques will get the job done. As it often is, scenario and preference of the developer is where the real decision lies of which way to go.

 

Happy Coding Smile

Advertisements

About Gregg Coleman

I am Senior-level Software Engineer working primarily these days with .NET. I have a good working knowledge of ASP.NET MVC, Web Forms, WCF web services and Windows Services. I spend much of my time in the Web Services (SOAP and REST) world in my current job designing and implementing various SOA architectures. I have been in the software engineering industry for about 6 years now and will not now nor ever consider myself an "expert" in programming because there is always so much to learn. My favorite thing about designing software is there are always new emerging technologies and something to learn every day! My current job has me spending much of my job on the bleeding edge of technologies and changing gears all the time, so I'm never bored and always challenged. On my spare time I enjoy weight training, reading and venturing to new places near by. Of course programing and learning new technologies are another hobby of mine.
This entry was posted in .NET, .NET 4.5, ASP.NET, C#, Classes, DataAnnotation, Exception handling, Exceptions, Generics, MVC, Validation and tagged , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s