views:

2227

answers:

6

I just want to know how to validate (or clean) user input in ASP.NET MVC so that an HttpRequestValidationException will not be thrown regardless of the values submitted. For example, with a text input, if the user inputs <BR/>, it will cause an exception and the Yellow Screen of Death will be shown. I don't want that. I want to catch the exception and to make visible an user friendly error in the current view, preferably with the controls loaded with the same values submitted.

I have found this http://www.romsteady.net/blog/2007/06/how-to-catch-httprequestvalidationexcep.html, but it is useless for my purpose. Also, I have found this http://msdn.microsoft.com/en-us/library/aa973813.aspx and tried to put inside a model binder but I couldn't make to work.

A: 

Put put ValidateRequest="false" to your aspx view declaration, but sanitize users input text inside your code, to avoid some xss attacks.

Hrvoje
Thanks, but I don't want to deactivate ValidateRequest on my aspx.
eKek0
+1  A: 

Instead of catching the error in the global.asax Application_Error, you could catch it by adding an error handler for the controller that explicitly catches this error and redirects to the view with an error message and appropriate view data.

I found this, somewhat old, post on how to do this with attributes.

tvanfosson
Thanks, I will try it for now
eKek0
A: 
alert();
+10  A: 

With the latest version of ASP.NET MVC (the RC, at the time of writing this) you can just put an attribute on either your controller class or your action method, e.g.:

[ValidateInput(false)]
public ActionResult create()
{
 // ...method body
}

The ValidateInputAttribute is in System.Web.Mvc.

But as others have said, you do then have to perform your own manual input validation or cleaning.

It'd be so nice if ValidateInputAttribute would accept the name of a field (or a list of names), so that validation could be turned off selectively. All or nothing tends to suck, cause duplication of effort, and generally just makes things more troublesome.
Chris Charabaruk
Using MVC 3, you must also ensure this is in your Web.config: `<httpRuntime requestValidationMode="2.0" />`
Drew Noakes
+1  A: 

ValidateInputAttribute is the proper method for disabling request validation. Declarative method within view (aspx) doesn't work because controller is responsible for receiving request (not view/aspx).

dario-g
+2  A: 

For a very detailed example of how to catch this (and other) exceptions with a filter see: http://code.google.com/p/geochat/source/browse/trunk/Source/Web/GeoChat.MvcExtensions/ExceptionHandlerAttribute.cs?spec=svn1730&amp;r=1730

This will allow you to keep the validation on, but prevent the user from seeing the "yellow screen of death".

This is a simplified (perhaps oversimplified) version:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true), AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class ExceptionHandlerAttribute : FilterAttribute, IExceptionFilter {

private HandleErrorAttribute attribute = new HandleErrorAttribute();

public ExceptionHandlerAttribute() {
  this.ExceptionType = typeof(Exception);
  this.Order = 1;
}

public string View {
  get {
    return attribute.View;
  }
  set {
    attribute.View = value;
  }
}

public Type ExceptionType {
  get {
    return attribute.ExceptionType;
  }
  set {
    attribute.ExceptionType = value;
  }
}

public void OnException(ExceptionContext filterContext) {
  if (this.ExceptionType.IsInstanceOfType(filterContext.Exception)) {
    string controller = (string)filterContext.RouteData.Values["controller"];
    string action = (string)filterContext.RouteData.Values["action"];
    if (controller == null)
      controller = String.Empty;

    if (action == null)
      action = String.Empty;

    HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controller, action);
    ViewResult result = new ViewResult();
    result.ViewName = this.View;
    result.MasterName = String.Empty;
    result.ViewData = new ViewDataDictionary<HandleErrorInfo>(model);

    result.TempData = filterContext.Controller.TempData;
    filterContext.Result = result;

    filterContext.ExceptionHandled = true;
    filterContext.HttpContext.Response.Clear();
    filterContext.HttpContext.Response.StatusCode = 500;
  }
}

}

JoshNaro