Blog

ASP.NET MVC Request Validation Protection: AllowHtml Attribute

By Martin Schaeferle | August 09, 2012

MVC has always included the same kind of request validation protection that is turned on by default, although you could turn it off by using the ValidateInput attribute with an argument of false. But that has proven to be too blunt a tool for many applications. If you had a single property of a model that could legitimately contain HTML markup-and you protected against crosssite scripting attacks programmatically-you had to turn off request validation for the entire action method.

 

In MVC 3, there is a better way: the AllowHtml attribute, which you can apply to individual properties of a model. This makes the attribute behave more like other model property-based validation attributes, and gives you very granular control over how request validation is applied. The sample application has a Notes property on the Dog class. If you use the default request validation behavior and add HTML markup to the contents of the Notes field as shown in Figure 22, when you submit the form the application will throw an HttpRequestValidationException as shown in Figure 23. This is a trappable exception that a real application should handle more gracefully than letting the user see a yellow screen of death. Edit Action Method

Figure 22. Entering markup in a text field.

Figure 23. HttpRequestValidationException as a result of request validation in an MVC application.

If you want to allow HTML markup in the Notes field, simply decorate the property in the Dog model class with the AllowHtml attribute as shown in the following code. With that in place, the application will save the data as regular string data. If you then view the details for the dog, as shown in Figure 24, you'll see the markup, although the "Irish Setter" part of the text will not appear in bold. Why not?

[AllowHtml()] public string Notes { get; set; } 

Figure 24. HTML markup displayed for a dog in the Notes field. The good news here is that this view encodes all strings displayed on the page. If you view the page source for the Details view shown in Figure 24, you'll see the following HTML. This is why the text isn't bolded and you see the markup.

<div class="display-label">Notes</div> <div class="display-field">Beautiful &lt;b&gt;Irish Setter&lt;/b&gt;.</div>

The Razor view engine encodes all text automatically for you, and if you use the Web forms view engine you can use the special code nugget delimiters <%: %> to encode text. This encoding in the view provides another layer of protection against cross-site scripting attacks, in this case against script and markup that are already infesting the data.

To turn off request validation for the entire model for an action method, you can still use the ValidateInput attribute with a value of false, as shown in the following code. This will allow markup in any of the text fields, as shown in Figure 25. This is not something you want to do lightly!

[HttpPost] [ValidateInput(false)] public ActionResult Edit(Models.Dog d) { ... 

Edit Action MethodFigure 25. The result of turning off request validation for the entire model in the Edit action method.

Get more training on ASP.NET MVC 2 & 3!



Martin Schaeferle

Martin Schaeferle has taught IT professionals nationwide to develop applications using Visual Basic, Microsoft SQL Server, ASP, and XML. He has been a featured speaker at Microsoft Tech-Ed and the Microsoft NCD Channel Summit, and he specializes in developing Visual Basic database applications, COM-based components, and ASP-based Web sites. In addition to writing and presenting technical training content, Martin is also LearnNowOnline's vice president of technology.


This blog entry was originally posted August 09, 2012 by Martin Schaeferle