How do I override RequestValidation in ASP.NET WebAPI
Asked Answered
O

4

12

I'm having problems with requests that include 'dangerous characters' as part of a Web API URL. The Url includes an & which is properly Url encoded, but still causes a Request Validation ASP.NET error.

Unlike MVC there appears to be no [ValidateInput(false)] attribute to force and disable this functionality.

Overmuch answered 14/3, 2012 at 8:28 Comment(0)
O
8

Turns out the answer is to do this in web.config using:

<system.web>
  <httpRuntime requestPathInvalidCharacters="" />  
</system.web>

You can set this globally or at the sub-directory level. You can leverage the <location path=""> element to specify this setting only underneath certain paths. For example, if your Web API route that was affected lived underneath api/images you could do the following:

<location path="api/images">
  <system.web>
    <httpRuntime requestPathInvalidCharacters="" />  
  </system.web>
</location>

More information: https://msdn.microsoft.com/en-us/library/e1f13641(v=vs.100).aspx

Overmuch answered 14/3, 2012 at 8:49 Comment(2)
This is the only solution that worked for me. Adding requestValidationMode='2.0' to the web.config and trying the [ValidateInput(false)] attribute on the action method did NOT work. It started working after I added requestPathInvalidCharacters="". I think this is because the error here is part of Request.Path validation rather than Request.Form validation.Occur
It does not need to be global, just use location element to restrict path. So if your Web API route is under api/foo you can restrict location to path="api/foo" and add the httpRuntime configuration there. Confirmed this works fine in IIS. Also MSDN explictly states <httpRuntime> can be "declared at the machine, site, application, and subdirectory levels". I updated the answer.Nutrient
O
3

With RequestValidation set to 4.0 in the configuration the answer is no. You can however revert back to 2.0 Request Validation in which case the MVC attribute works as you would expect: Validate by default and explicitly override when needed.

<httpRuntime executionTimeout="300" requestValidationMode="2.0" />

Talked in detail about this and some of the options here: http://www.west-wind.com/weblog/posts/2010/Aug/19/RequestValidation-Changes-in-ASPNET-40

Overmuch answered 10/4, 2013 at 0:54 Comment(0)
A
3

You can get more fine-grained control over this by setting the requestValidationType attribute of the httpRuntime element to a custom type that inherits from System.Web.Util.RequestValidator and overrides IsValidRequestString.

Unfortunately this isn't part of the WebAPI pipeline, so can't directly check for things like action filters (i.e. attributes on controller methods).

However, if you specifically care about the Validation of Form fields, the Validator doesn't get called on these until you access them, which happens after Action Filters are fired, so you can opt-out of validation using an attribute by creating classes like the following...

public class AllowFormHtmlAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        HttpContext.Current.Items["AllowFormHtml"] = true;
    }
}

public class CustomRequestValidator : RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        if (context.Items["AllowFormHtml"] as bool? == true && requestValidationSource == RequestValidationSource.Form)
        {
            validationFailureIndex = 0;
            return true;
        }

        return base.IsValidRequestString(
            context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }
}

... Then just annotating your controller method with [AllowFormHtml]

However, if you're accessing form fields directly from the HttpRequest, it's simpler to use HttpRequest.Unvalidated, which bypasses validation.

Anhydrite answered 22/7, 2015 at 14:29 Comment(0)
S
2

per @Levi our Web Security guy:

Config is the only way to do this. Even MVC’s [ValidateInput(false)] wouldn’t help with this particular scenario.

Disabling it in Web.config isn’t necessary a terrible idea. If you’re following good security practice by validating and encoding untrusted data, it’s perfectly fine to apply it application-wide.

Surly answered 10/4, 2013 at 0:41 Comment(1)
[ValidateInput(false)] does not work in my case. I think it's because [ValidateInput(false)] refers to the Request.Form rather than Request.Path.Occur

© 2022 - 2024 — McMap. All rights reserved.