Friday, February 04, 2011

ASP.NET MVC - Excluding Model Validation Rules

While building a simple MVC app, I came across the problem where I am using one model in several views. The model includes DataAnnotation attribute rules for validation. However, some rules don't apply to certain views. It seems this is a common problem, without a well established solution. After searching a bit, I found this post by Andrew West that nicely summarizes the problem and several solutions. His last suggestion is to remove the items from ModelState that you don't want to participate in the validation. I agreed that this was the simplest and least dependent solution and pursued it.

What I finally came up with was a simple extension method for the ModelStateDictionary that looks like this:
public static void CleanAllBut(
this ModelStateDictionary modelState,
params string[] includes)
{
modelState
.Where(x => !includes
.Any(i => String.Compare(i, x.Key, true) == 0))
.ToList()
.ForEach(k => modelState.Remove(k));
}

The method removes everything in the model state dictionary that doesn't match one of the "includes" strings. Being a params argument to the method, the call to it becomes very clean and readable (unlike the extension method itself). So I added this call to my controller method:
ModelState.CleanAllBut("username", "password");

While we can use the existing ModelStateDictionary.Remove() method for when we only want to explicitly remove one item, for multi-key removal we could make a similar extension method that takes a list of keys to remove.