Granular Request Validation in ASP.NET MVC 3 Beta

11/9 Update: This article only applies to the MVC 3 Beta release. I have a new post about AllowHtmlAttribute that describes the new APIs and behaviors available in MVC 3 RC and later.

If you don’t know already, we have just released the ASP.NET MVC 3 Beta and it brings a slew of new features. A small but useful feature is what we call granular request validation. It allows you to opt out of ASP.NET’s request validation on a field-by-field basis, meaning that it will be a lot easier now to write forms that accept HTML user input (think smart text boxes like TinyMCE, etc.) for some of the fields while at the same time maintaining the built-in security for the rest.

Request Validation is a core ASP.NET feature that helps in preventing cross-site scripting (XSS) and other flavors of HTML injection attacks. It works by examining incoming requests and blocking when any client-supplied data (such as through form fields or the query string) contains potentially dangerous input (for example, the less-than character ‘<’). It is turned on by default and the you have to explicitly disable it if you want to accept HTML-formatted user input. However, until now this was an all-or-nothing setting and turning it off meant that you had to take extra steps to manually validate all of the inputs for malicious content.

In ASP.NET MVC you can control whether an action should have request validation performed using ValidateInputAttriubte. For example the following usage will disable request validation:

 [ValidateInput(false)]
public ActionResult MyAction() { ... }

Note for ASP.NET 4: because of the hardening of request validation in .NET 4 for the above usage to actually work in MVC 2 you had to revert to 2.0 behavior by changing a setting in web.config:

 <httpRuntime requestValidationMode="2.0" />

MVC 3 Beta introduces a new property on ValidateInputAttribute called Exclude. Using this property you can opt out of request validation for only some of your fields. For example, take the following User model:

 public class User {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public string Description { get; set; }
    public string Bio { get; set; }
}

If you want your users to be able to edit their Bio or Description and insert arbitrary markup into those two fields while at the same time ensuring no markup makes its way into the Name or Email fields you can annotate your action in the following manner:

 [ValidateInput(true, Exclude="Bio, Description")]
public ActionResult Edit(User user) { ... }

The Exclude property takes in a string with a comma-separated list of property/field names that should not be validated. All other fields in the incoming request will be validated and blocked if dangerous input is detected.

With this Beta release it is also no longer necessary to set your application to 2.0 request validation mode. You benefit from .NET 4’s more secure behavior while at the same time being able to allow unvalidated HTML input only on the fields of your choosing.