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
//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".