back to Jitbit Blog home About this blog

ASP.NET MVC: Allowing Html for Particular Action Parameters

by Alex Yumashev · Updated Sep 10 2019

Sometimes you need to allow users to post HTML to the server. And, by default, this is the error you're going to get:

A potentially dangerous Request.Form value was detected from the client

The recommended way of solving this is by adding an [AllowHtml] attribute to the model property:

public class BlogPost
{
    public int UserId { get; set; }
    
    [AllowHtml]
    public string HtmlBody { get; set; }
}

But what do you do if you're not using a model, but need to skip validation for a particular action parameter?

Some people recommended adding [ValidateInput(false)] to the whole action method, but DON'T DO THAT this puts your app at risk disabling validation for all user input, not just one parameter.

In MVC 3 Beta it was posible to do this:

//does not work any more :(
[HttpPost, ValidateInput(true, Exclude = "fieldName")]
public virtual ActionResult Save(int id, string fieldName)
{
   //...
}

But this has been removed from the release

So how do you skip validation for particular parameters, not a model property?

//we need to allow html for "htmlBody" only
public ActionResult AddBlogPost(int userId, string htmlBody)
{
    //...
}

Meet custom model binding. The beauty of it is that you can apply custom binders at parameter level. Like this:

public ActionResult AddBlogPost(int userId,
    [ModelBinder(typeof(AllowHtmlBinder))] string htmlBody)
{
    //...
}

And this is the custom binder we're using above:

public class AllowHtmlBinder : IModelBinder
{
	public object BindModel(ControllerContext controllerContext,
	    ModelBindingContext bindingContext)
	{
		var request = controllerContext.HttpContext.Request;
		var name = bindingContext.ModelName;
		return request.Unvalidated[name]; //magic happens here
	}
}

As you can see I'm accessing the request field using Request.Unvalidated property here, which skips the validation. It was introduced in .NET Framework 4.5 for this exact purpose: "Use this method if you anticipate that the request will contain markup".