Every time a user posts something containing < or > in a page in my web application, I get this exception thrown.

I don't want to go into the discussion about the smartness of throwing an exception or crashing an entire web application because somebody entered a character in a text box, but I am looking for an elegant way to handle this.

Trapping the exception and showing

An error has occurred please go back and re-type your entire form again, but this time please do not use <

doesn't seem professional enough to me.

Disabling post validation (validateRequest="false") will definitely avoid this error, but it will leave the page vulnerable to a number of attacks.

Ideally: When a post back occurs containing HTML restricted characters, that posted value in the Form collection will be automatically HTML encoded. So the .Text property of my text-box will be something & lt; html & gt;

Is there a way I can do this from a handler?

60 upvote
  flag
Note that you can get this error if you have HTML entity names (&amp;) or entity numbers (&#39;) in your input too. – Drew Noakes
upvote
  flag
check here – gofor.net
1 upvote
  flag
@bamccaig , kinda missing the point entirely – Radu094
11 upvote
  flag
@Radu094, the point is that angle brackets are not the least bit dangerous. Incompetent Web developers are. As emphasized by the fact that we can type them into our comments right here on SO and nothing bad is happening! ZOMG, how do they do it?! <script type="text/javascript">alert("Attack!");</script> Awww. – bambams
13 upvote
  flag
Well, since it's my question I feel I can define what the point actually is: crashing an entire application process and returning a generic error message because somebody typed a '<' is overkill. Especially since you know most people will just 'validateRequest=false' to get rid of it, thus re-opening the vulnerability – Radu094
6 upvote
  flag
@DrewNoakes: entity names (&amp;) do not seem to be a problem according to my tests (tested in .Net 4.0), although entity numbers (&#39;) do fail validation (as you said). If you disassemble the System.Web.CrossSiteScriptingValidation.IsDangerousString method using .Net Reflector, you'll see that the code looks specifically for html tags (starting with <) and entity numbers (starting with &#) – Gyum Fox
3 upvote
  flag
Create a new site in VS2014 using the default MVC project and run it. Click the register link, add any email, and use "<P455-0r[!" as the password. Same error out of the box, not trying to do anything malicious, the password field won't be displayed so it won't be a XSS attack, but the only way to fix it is to completely remove validation with the ValidateInput(false)? The AllowHtml suggestion doesn't work in this situation, still blew up with the same error. A potentially dangerous Request.Form value was detected from the client (Password="<P455-0r[!"). – stephenbayer
upvote
  flag
TL;DR put <httpRuntime requestValidationMode="2.0" /> in web.config – Björn Ali Göransson

36 Answers 11

You can HTML encode text box content, but unfortunately that won't stop the exception from happening. In my experience there is no way around, and you have to disable page validation. By doing that you're saying: "I'll be careful, I promise."

You should use the Server.HtmlEncode method to protect your site from dangerous input.

More info here

2 upvote
  flag
Use the Anti-XSS Library to prevent this error... this is incomplete. – LamonteCristo
up vote 960 down vote accepted

I think you are attacking it from the wrong angle by trying to encode all posted data.

Note that a "<" could also come from other outside sources, like a database field, a configuration, a file, a feed and so on.

Furthermore, "<" is not inherently dangerous. It's only dangerous in a specific context: when writing strings that haven't been encoded to HTML output (because of XSS).

In other contexts different sub-strings are dangerous, for example, if you write an user-provided URL into a link, the sub-string "javascript:" may be dangerous. The single quote character on the other hand is dangerous when interpolating strings in SQL queries, but perfectly safe if it is a part of a name submitted from a form or read from a database field.

The bottom line is: you can't filter random input for dangerous characters, because any character may be dangerous under the right circumstances. You should encode at the point where some specific characters may become dangerous because they cross into a different sub-language where they have special meaning. When you write a string to HTML, you should encode characters that have special meaning in HTML, using Server.HtmlEncode. If you pass a string to a dynamic SQL statement, you should encode different characters (or better, let the framework do it for you by using prepared statements or the like)..

When you are sure you HTML-encode everywhere you pass strings to HTML, then set validateRequest="false" in the <%@ Page ... %> directive in your .aspx file(s).

In .NET 4 you may need to do a little more. Sometimes it's necessary to also add <httpRuntime requestValidationMode="2.0" /> to web.config (reference).

upvote
  flag
@Hightechrider thanks for that link. Simple setting validateRequest="false" doesn't work for a view in ASP.Net MVC @olavk - Nice. Joel took the time to comment on your answer. – IEnumerator
68 upvote
  flag
To those coming in late: validateRequest="false" goes in the Page directive (first line of your .aspx file) – MGOwen
50 upvote
  flag
Tip: Put <httpRuntime requestValidationMode="2.0" /> in a location tag to avoid killing the useful protection provided by validation from the rest of your site. – Brian
upvote
  flag
Looks like <httpRuntime requestValidationMode="2.0" /> works only when 2.0 framework is installed on the machine. What if 2.0 framework is not installed at all but only 4.0 framework is installed? – Samuel
265 upvote
  flag
In MVC3, this is [AllowHtml] on the model property. – Jeremy Holovacs
2 upvote
  flag
To disable it globally for MVC 3 you also need GlobalFilters.Filters.Add(new ValidateInputAttribute(false)); in Application_Start(). – Alex
14 upvote
  flag
@MGOwen you can also add the page directive to the web.config via <pages validateRequest="false" /> in <system.web />. Doing so will apply the property to all pages. – LordScree
2 upvote
  flag
This answer to this question has a reference to setting the requestValidationMode="2.0" for only a single page on your site, which is definitely more secure than turning the validation off for an entire site. – Steve Wranovsky
37 upvote
  flag
In MVC4, [ValidateInput(false)] works. – Adam K Dean
upvote
  flag
You can use CausesValidation="false" on specific controls in WebForms. – Justin Skiles
1 upvote
  flag
I would like to point out that not only "javascript:" can be dangerous. Imagine what would "</div></div>" do to your layout. – Vojtech B
upvote
  flag
Is there any method other than disabling validateRequest, since it threatens the security of the web site. – NCA
upvote
  flag
I just want to point out that dynamic SQL running on SQL Server should always be executed using sp_executesql to reduce security risk. – devinbost
upvote
  flag
@Samuel: requestValidationMode="4.0" (or anything >= 4.0) means that the validation is done whenever a HTTP request data is accessed (url, cookies). requestValidationMode="2.0" (or anything less than 4.0) is to enable HTTP request validation for pages only. Take a look at the MSDN: msdn.microsoft.com/en-us/library/… – Dio Phung
upvote
  flag
@AdamKDean [ValidateInput(false)] only works if the offending characters are in the query string. If they're in the request path, this doesn't work – PandaWood
1 upvote
  flag
In ASP.NET MVC, Razor has automatically HTML-encoded strings since 2010. So I think one can use [ValidateInput(false)] on one's POST controller actions (that receive form data) safely? – nmit026
upvote
  flag
@JustinSkiles CausesValidation only changes so the field does not trigger validation of field validators like RequiredFieldValidator. – Peter
upvote
  flag
for .net 4 requestvalidationmode is needed inside web.config too – masoud Cheragee
upvote
  flag
@JeremyHolovacs Spent hours pulling my hair out over this. Thank you so much!!!! – blueprintChris
upvote
  flag
why this issue not occuring in local host,but only occurs on server just curious to know..however your solution of adding validate request=false worked fine for me – clarifier

I guess you could do it in a module; but that leaves open some questions; what if you want to save the input to a database? Suddenly because you're saving encoded data to the database you end up trusting input from it which is probably a bad idea. Ideally you store raw unencoded data in the database and the encode every time.

Disabling the protection on a per page level and then encoding each time is a better option.

Rather than using Server.HtmlEncode you should look at the newer, more complete Anti-XSS library from the Microsoft ACE team.

As long as these are only "<" and ">" (and not the double quote itself) characters and you're using them in context like <input value="this" />, you're safe (while for <textarea>this one</textarea> you would be vulnerable of course). That may simplify your situation, but for anything more use one of other posted solutions.

Disable the page validation if you really need the special characters like, >, , <, etc. Then ensure that when the user input is displayed, the data is HTML-encoded.

There is a security vulnerability with the page validation, so it can be bypassed. Also the page validation shouldn't be solely relied on.

See: http://www.procheckup.com/PDFs/bypassing-dot-NET-ValidateRequest.pdf

upvote
  flag
The link is broken. – Peter Mortensen

If you're just looking to tell your users that < and > are not to be used BUT, you don't want the entire form processed/posted back (and lose all the input) before-hand could you not simply put in a validator around the field to screen for those (and maybe other potentially dangerous) characters?

Please bear in mind that some .NET controls will automatically HTML encode the output. For instance, setting the .Text property on a TextBox control will automatically encode it. That specifically means converting < into &lt;, > into &gt; and & into &amp;. So be wary of doing this...

myTextBox.Text = Server.HtmlEncode(myStringFromDatabase); // Pseudo code

However, the .Text property for HyperLink, Literal and Label won't HTML encode things, so wrapping Server.HtmlEncode(); around anything being set on these properties is a must if you want to prevent <script> window.location = "http://www.google.com"; </script> from being output into your page and subsequently executed.

Do a little experimenting to see what gets encoded and what doesn't.

If you don't want to disable ValidateRequest you need to implement a JavaScript function in order to avoid the exception. It is not the best option, but it works.

function AlphanumericValidation(evt)
{
    var charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode :
        ((evt.which) ? evt.which : 0));

    // User type Enter key
    if (charCode == 13)
    {
        // Do something, set controls focus or do anything
        return false;
    }

    // User can not type non alphanumeric characters
    if ( (charCode <  48)                     ||
         (charCode > 122)                     ||
         ((charCode > 57) && (charCode < 65)) ||
         ((charCode > 90) && (charCode < 97))
       )
    {
        // Show a message or do something
        return false;
    }
}

Then in code behind, on the PageLoad event, add the attribute to your control with the next code:

Me.TextBox1.Attributes.Add("OnKeyPress", "return AlphanumericValidation(event);")
4 upvote
  flag
This will still leave the app vulnerable from made-up POST requests. A regular user will have problems entering characters like , : or quotes, but a regular hacker will have no problems POSTing malformed data to the server. I'd vode this waaay down. – Radu094
10 upvote
  flag
@Radu094: This solution allows you to keep ValidateRequest=true, which means hackers will still hit that wall. Vote UP, since this leaves you less vulnerable than turning ValidateRequest off. – jbehren

There's a different solution to this error if you're using ASP.NET MVC:

Visual Basic sample:

<AcceptVerbs(HttpVerbs.Post), ValidateInput(False)> _
Function Edit(ByVal collection As FormCollection) As ActionResult
    ...
End Function

C# sample:

[HttpPost, ValidateInput(false)]
public ActionResult Edit(FormCollection collection)
{
    // ...
}
upvote
  flag
the problem may be come when it's need on one page of whole application – Steven Spielberg
3 upvote
  flag
You can also add the [ValidateInput(false)] attribute at the class level. If you add it to your base controller class, it will apply to all controller method actions. – Shan Plourde
upvote
  flag
@Zack Thanks for the solution. On the other hand I am wondering if [AllowHtml] is better than ValidateInput(false), because [AllowHtml]is defined at once for a property i.e. Editor field and whenever it is used there is no need to use it for several actions. What do you suggest? – Clint Eastwood
upvote
  flag
@Zack Peterson Is it safe to use? No security issue? – shrey Pav

You can catch that error in Global.asax. I still want to validate, but show an appropriate message. On the blog listed below, a sample like this was available.

    void Application_Error(object sender, EventArgs e)
    {
        Exception ex = Server.GetLastError();

        if (ex is HttpRequestValidationException)
        {
            Response.Clear();
            Response.StatusCode = 200;
            Response.Write(@"[html]");
            Response.End();
        }
    }

Redirecting to another page also seems like a reasonable response to the exception.

http://www.romsteady.net/blog/2007/06/how-to-catch-httprequestvalidationexcep.html

upvote
  flag
seems a simple thing but has been difficult to find so I gave you a vote up... – phillip

If you are on .NET 4.0 make sure you add this in your web.config file inside the <system.web> tags:

<httpRuntime requestValidationMode="2.0" />

In .NET 2.0, request validation only applied to aspx requests. In .NET 4.0 this was expanded to include all requests. You can revert to only performing XSS validation when processing .aspx by specifying:

requestValidationMode="2.0"

You can disable request validate entirely by specifying:

validateRequest="false"
29 upvote
  flag
Inside the <system.web> tags. – Hosam Aly
7 upvote
  flag
I've put this in the web.config, but still to the error "A potentially dangerous Request.Form value " – Filip
19 upvote
  flag
Looks like <httpRuntime requestValidationMode="2.0" /> works only when 2.0 framework is installed on the machine. What if 2.0 framework is not installed at all but only 4.0 framework is installed? – Samuel
upvote
  flag
This totally worked for me. None of the steps document in the other answers were necessary (including validateRequest="false")! – tom redfern
upvote
  flag
This fixed my current problem. Thank you! – Dyrborg

The previous answers are great, but nobody said how to exclude a single field from being validated for HTML/JavaScript injections. I don't know about previous versions, but in MVC3 Beta you can do this:

[HttpPost, ValidateInput(true, Exclude = "YourFieldName")]
public virtual ActionResult Edit(int id, FormCollection collection)
{
    ...
}

This still validates all the fields except for the excluded one. The nice thing about this is that your validation attributes still validate the field, but you just don't get the "A potentially dangerous Request.Form value was detected from the client" exceptions.

I've used this for validating a regular expression. I've made my own ValidationAttribute to see if the regular expression is valid or not. As regular expressions can contain something that looks like a script I applied the above code - the regular expression is still being checked if it's valid or not, but not if it contains scripts or HTML.

10 upvote
  flag
Sadly it looks like the Exclude feature was removed from MVC 3 RTW :( – Matt Greer
2 upvote
  flag
Nor was it included in MVC 4 – wilsjd
8 upvote
  flag
Use [AllowHtml] on the model's properties instead of [ValidateInput] on the Action to achieve the same end result. – Mrchief
upvote
  flag
@gligoran Is [AllowHtml] better than ValidateInput(false) for Editor fields? Because [AllowHtml]is defined at once for a property i.e. Editor field and whenever it is used there is no need to use it for several actions. What do you suggest? – Clint Eastwood
2 upvote
  flag
@Christof Note that my answer is 5 years old. I haven't come across this problem in a really long while, so there might be a lot better ways of dealing with it. Regarding this two options I think it depends on your situation. Maybe you expose that model in more than one actions and in some places HTML is allowed or not. In such a case [AllowHtml] isn't an options. I recommend checking out this article: weblogs.asp.net/imranbaloch/…, but it too is somewhat old and might be out of date. – gligoran
upvote
  flag
@gligoran Ok, thanks. I tried to use [AllowHtml] in MVC5, but see that ValidateInput(false) is better and has no problem. Thanks again for your reply. – Clint Eastwood

In ASP.NET MVC you need to set requestValidationMode="2.0" and validateRequest="false" in web.config, and apply a ValidateInput attribute to your controller action:

<httpRuntime requestValidationMode="2.0"/>

<configuration>
    <system.web>
        <pages validateRequest="false" />
    </system.web>
</configuration>

and

[Post, ValidateInput(false)]
public ActionResult Edit(string message) {
    ...
}
2 upvote
  flag
For me, validateRequest="false" was not necessary, only requestValidationMode="2.0" – tom redfern
upvote
  flag
requestValidationMode="2.0" still generates the error with HTMLencoded data. No solution except to base64 encode everything, then send it along. – MC9000

In ASP.NET MVC 3, you can add the AllowHtml attribute to a property on your model.

It allows a request to include HTML markup during model binding by skipping request validation for the property.

[AllowHtml]
public string Description { get; set; }
11 upvote
  flag
Much better to do this declarativly than in the controller! – Andiih
18 upvote
  flag
The only correct answer! disabling validation on controller action is hacky. And for disabling validation on application level, devs must be hanged! – trailmax
6 upvote
  flag
Beautiful! This is the way it should be done. – beautifulcoder
upvote
  flag
this seems to be the cleanest approach. – r3try
3 upvote
  flag
@AnthonyJohnston Can it also be used in MVC 4 and MVC 5? Thanks... – Clint Eastwood
upvote
  flag
Did this disappear in MVC 4? – granadaCoder
upvote
  flag
It seems to only be in DotNet 4.0 Framework. msdn.microsoft.com/en-us/library/… Do What??? – granadaCoder
upvote
  flag
This is THE way. – VSG24
upvote
  flag
thanks dude...your are great...i really appreciate this answer..thanks...thanks..2 hour wasted in finding y i get this error – Rakeshyadvanshi
upvote
  flag
What is the difference between ValidateInput(false) and AllowHtml? What is the advantage of one over the other? When would i want to use AllowHtml instead of ValidateInput(false)? When would i want to use ValidateInput(false) over AllowHtml? When would i want to use both? Does it make sense to use both? – Ian Boyd
upvote
  flag
ValidateInput is on the method, AllowHtml is on the property of the model - so you only allow the one you expect to have html - not all – Anthony Johnston

It seems no one has mentioned the below yet, but it fixes the issue for me. And before anyone says yeah it's Visual Basic... yuck.

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Example.aspx.vb" Inherits="Example.Example" **ValidateRequest="false"** %>

I don't know if there are any downsides, but for me this worked amazing.

upvote
  flag
Works for web forms c# or VB – TheAlbear
upvote
  flag
this is the only one that worked for me – Dinesh Rajan

You could also use JavaScript's escape(string) function to replace the special characters. Then server side use Server.URLDecode(string) to switch it back.

This way you don't have to turn off input validation and it will be more clear to other programmers that the string may have HTML content.

In the web.config file, within the tags, insert the httpRuntime element with the attribute requestValidationMode="2.0". Also add the validateRequest="false" attribute in the pages element.

Example:

<configuration>
  <system.web>
   <httpRuntime requestValidationMode="2.0" />
  </system.web>
  <pages validateRequest="false">
  </pages>
</configuration>
1 upvote
  flag
For me, validateRequest="false" was not necessary, only requestValidationMode="2.0" – tom redfern
3 upvote
  flag
The "pages" section must be within the "system.web" section. – Carter Medlin
upvote
  flag
dangerous answer, once again. – MC9000
upvote
  flag
I needed both. Thanks – Jack

The other solutions here are nice, however it's a bit of a royal pain in the rear to have to apply [AllowHtml] to every single Model property, especially if you have over 100 models on a decent sized site.

If like me, you want to turn this (IMHO pretty pointless) feature off site wide you can override the Execute() method in your base controller (if you don't already have a base controller I suggest you make one, they can be pretty useful for applying common functionality).

    protected override void Execute(RequestContext requestContext)
    {
        // Disable requestion validation (security) across the whole site
        ValidateRequest = false;
        base.Execute(requestContext);
    }

Just make sure that you are HTML encoding everything that is pumped out to the views that came from user input (it's default behaviour in ASP.NET MVC 3 with Razor anyway, so unless for some bizarre reason you are using Html.Raw() you shouldn't require this feature.

In ASP.NET, you can catch the exception and do something about it, such as displaying a friendly message or redirect to another page... Also there is a possibility that you can handle the validation by yourself...

Display friendly message:

protected override void OnError(EventArgs e)
{
    base.OnError(e);
    var ex = Server.GetLastError().GetBaseException();
    if (ex is System.Web.HttpRequestValidationException)
    {
        Response.Clear();
        Response.Write("Invalid characters."); //  Response.Write(HttpUtility.HtmlEncode(ex.Message));
        Response.StatusCode = 200;
        Response.End();
    }
}

I ended up using JavaScript before each postback to check for the characters you didn't want, such as:

<asp:Button runat="server" ID="saveButton" Text="Save" CssClass="saveButton" OnClientClick="return checkFields()" />

function checkFields() {
    var tbs = new Array();
    tbs = document.getElementsByTagName("input");
    var isValid = true;
    for (i=0; i<tbs.length; i++) {
        if (tbs(i).type == 'text') {
            if (tbs(i).value.indexOf('<') != -1 || tbs(i).value.indexOf('>') != -1) {
                alert('<> symbols not allowed.');
                isValid = false;
            }
        }
    }
    return isValid;
}

Granted my page is mostly data entry, and there are very few elements that do postbacks, but at least their data is retained.

upvote
  flag
There should be big brackets instead of small brackets. Like ` if (tbs[i].type == 'text') {` in place of ` if (tbs(i).type == 'text') {` – Shilpa Soni

I was getting this error too.

In my case, a user entered an accented character á in a Role Name (regarding the ASP.NET membership provider).

I pass the role name to a method to grant Users to that role and the $.ajax post request was failing miserably...

I did this to solve the problem:

Instead of

data: { roleName: '@Model.RoleName', users: users }

Do this

data: { roleName: '@Html.Raw(@Model.RoleName)', users: users }

@Html.Raw did the trick.

I was getting the Role name as HTML value roleName="Cadastro b&#225;s". This value with HTML entity &#225; was being blocked by ASP.NET MVC. Now I get the roleName parameter value the way it should be: roleName="Cadastro Básico" and ASP.NET MVC engine won't block the request anymore.

For ASP.NET 4.0, you can allow markup as input for specific pages instead of the whole site by putting it all in a <location> element. This will make sure all your other pages are safe. You do NOT need to put ValidateRequest="false" in your .aspx page.

<configuration>
...
  <location path="MyFolder/.aspx">
    <system.web>
      <pages validateRequest="false" />
      <httpRuntime requestValidationMode="2.0" />
    </system.web>
  </location>
...
</configuration>

It is safer to control this inside your web.config, because you can see at a site level which pages allow markup as input.

You still need to programmatically validate input on pages where request validation is disabled.

upvote
  flag
More info on requestValidationMode=2|4 here: msdn.microsoft.com/en-us/library/… – GlennG
upvote
  flag
Sadly this won't work with ASP.net 2.0 as is. Remove the httpRuntime line and it will work. – Fandango68
upvote
  flag
you still have validateRequest="false" - VERY BAD!!! – MC9000
upvote
  flag
I added a warning reminding people to manually validate input when validation is disabled. – Carter Medlin
upvote
  flag
This solution worked perfectly for me. Thank you. – aspnetdeveloper

None of the suggestions worked for me. I did not want to turn off this feature for the whole website anyhow because 99% time I do not want my users placing HTML on web forms. I just created my own work around method since I'm the only one using this particular application. I convert the input to HTML in the code behind and insert it into my database.

The answer to this question is simple:

var varname = Request.Unvalidated["parameter_name"];

This would disable validation for the particular request.

1 upvote
  flag
Only applicable for ASP.NET 4.5 (and, presumably, whatever will come after it.) Pre 4.5 does not support this. – Beska
2 upvote
  flag
I wish I could bump this way up. I'm using .NET 4.5 and this is exactly what I needed since I'm not using MVC and I cannot change the web.config. – Chris Gillum
1 upvote
  flag
Yeah but what if you're using .Net 2? Some of us have no choice – Fandango68
upvote
  flag
this gets POST or GET parameters? – max4ever
upvote
  flag
Are you saying this prevents an exception that was already thrown? Or does .net 4.5 delay the exception and validation until data is actually read from the Request? – ebyrob
upvote
  flag
This was the only option I could use. I have to pull directly from the Request/Form, without using Models or Parameters in MVC. The other options still validated the input. – Jesse Sierks

You can use something like:

var nvc = Request.Unvalidated().Form;

Later, nvc["yourKey"] should work.

Another solution is:

protected void Application_Start()
{
    ...
    RequestValidator.Current = new MyRequestValidator();
}

public class MyRequestValidator: RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        bool result = base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);

        if (!result)
        {
            // Write your validation here
            if (requestValidationSource == RequestValidationSource.Form ||
                requestValidationSource == RequestValidationSource.QueryString)

                return true; // Suppress error message
        }
        return result;
    }
}
upvote
  flag
Nice! Wasn't aware of the ability to replace the Request Validator. Instead of just saying "ok" like you do I extended this idea to not validate fields that end in "_NoValidation" as their name. Code below. – Walden Leverich
upvote
  flag
Walden Leverich, to do this see [AllowHtml] attribure – Sel
upvote
  flag
Sel, yes in an MVC environment that would work. But in a webforms application I don't have a model to do that on. :-) – Walden Leverich

For MVC, ignore input validation by adding

[ValidateInput(false)]

above each Action in the Controller.

upvote
  flag
This doesn't seem to work in the case that it gets to the controller method via a configured route. – PandaWood
upvote
  flag
Actually, the technical explanation, is that this only works when the offending character is in the "query string"... if it's in the request path, Validation attribute does not work – PandaWood
upvote
  flag
Thanks. it worked. – Baqer Naqvi

As indicated in my comment to Sel's answer, this is our extension to a custom request validator.

public class SkippableRequestValidator : RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        if (collectionKey != null && collectionKey.EndsWith("_NoValidation"))
        {
            validationFailureIndex = 0;
            return true;
        }

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

I found a solution that uses JavaScript to encode the data, which is decoded in .NET (and doesn't require jQuery).

  • Make the textbox an HTML element (like textarea) instead of an ASP one.
  • Add a hidden field.
  • Add the following JavaScript function to your header.

    function boo() { targetText = document.getElementById("HiddenField1"); sourceText = document.getElementById("userbox"); targetText.value = escape(sourceText.innerText); }

In your textarea, include an onchange that calls boo():

<textarea id="userbox"  onchange="boo();"></textarea>

Finally, in .NET, use

string val = Server.UrlDecode(HiddenField1.Value);

I am aware that this is one-way - if you need two-way you'll have to get creative, but this provides a solution if you cannot edit the web.config

Here's an example I (MC9000) came up with and use via jQuery:

$(document).ready(function () {

    $("#txtHTML").change(function () {
        var currentText = $("#txtHTML").text();
        currentText = escape(currentText); // Escapes the HTML including quotations, etc
        $("#hidHTML").val(currentText); // Set the hidden field
    });

    // Intercept the postback
    $("#btnMyPostbackButton").click(function () {
        $("#txtHTML").val(""); // Clear the textarea before POSTing
                               // If you don't clear it, it will give you
                               // the error due to the HTML in the textarea.
        return true; // Post back
    });


});

And the markup:

<asp:HiddenField ID="hidHTML" runat="server" />
<textarea id="txtHTML"></textarea>
<asp:Button ID="btnMyPostbackButton" runat="server" Text="Post Form" />

This works great. If a hacker tries to post via bypassing JavaScript, they they will just see the error. You can save all this data encoded in a database as well, then unescape it (on the server side), and parse & check for attacks before displaying elsewhere.

upvote
  flag
This is a good solution. It's a proper manual way to control it yourself and not invalidate the entire website or page – Fandango68
upvote
  flag
Make sure to use an HTML markup, not an ASP.Net control (ie no runat="server") for the textarea, then use the ASP.Net hidden control for the hidden. This is the best solution I've seen w/o compromising anything. Naturally, you want to parse your data for XSS, SQL Injection on the server side, but at least you can post HTML – MC9000
upvote
  flag
escape(...) can take a long time. In my case, the markup was an entire (2MB) XML file. You might ask, "Why don't you just use <input type="file"... and... I agree with you :) – The Red Pea

Try with

Server.Encode

and

Server.HtmlDecode while sending and receiving.

1 upvote
  flag
dosn't work with < or > – mohsen solhnia
1 upvote
  flag
You can't even get that far (that is you can't post back, so nothing you do on the code-behind will work) with validation on - the point of the user's question. – MC9000

Cause

ASP.NET by default validates all input controls for potentially unsafe contents that can lead to cross-site scripting (XSS) and SQL injections. Thus it disallows such content by throwing the above exception. By default it is recommended to allow this check to happen on each postback.

Solution

On many occasions you need to submit HTML content to your page through Rich TextBoxes or Rich Text Editors. In that case you can avoid this exception by setting the ValidateRequest tag in the @Page directive to false.

<%@ Page Language="C#" AutoEventWireup="true" ValidateRequest = "false" %>

This will disable the validation of requests for the page you have set the ValidateRequest flag to false. If you want to disable this, check throughout your web application; you’ll need to set it to false in your web.config <system.web> section

<pages validateRequest ="false" />

For .NET 4.0 or higher frameworks you will need to also add the following line in the <system.web> section to make the above work.

<httpRuntime requestValidationMode = "2.0" />

That’s it. I hope this helps you in getting rid of the above issue.

Reference by: ASP.Net Error: A potentially dangerous Request.Form value was detected from the client

If you're using framework 4.0 then the entry in the web.config (<pages validateRequest="false" />)

<configuration>
    <system.web>
        <pages validateRequest="false" />
    </system.web>
</configuration>

If you're using framework 4.5 then the entry in the web.config (requestValidationMode="2.0")

<system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" requestValidationMode="2.0"/>
</system.web>

If you want for only single page then, In you aspx file you should put the first line as this :

<%@ Page EnableEventValidation="false" %>

if you already have something like <%@ Page so just add the rest => EnableEventValidation="false" %>

I recommend not to do it.

upvote
  flag
worked like a charm for me!!! – Marco Alves

You can automatically HTML encode field in custom Model Binder. My solution some different, I put error in ModelState and display error message near the field. It`s easy to modify this code for automatically encode

 public class AppModelBinder : DefaultModelBinder
    {
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            try
            {
                return base.CreateModel(controllerContext, bindingContext, modelType);
            }
            catch (HttpRequestValidationException e)
            {
                HandleHttpRequestValidationException(bindingContext, e);
                return null; // Encode here
            }
        }
        protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext,
            PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
        {
            try
            {
                return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
            }
            catch (HttpRequestValidationException e)
            {
                HandleHttpRequestValidationException(bindingContext, e);
                return null; // Encode here
            }
        }

        protected void HandleHttpRequestValidationException(ModelBindingContext bindingContext, HttpRequestValidationException ex)
        {
            var valueProviderCollection = bindingContext.ValueProvider as ValueProviderCollection;
            if (valueProviderCollection != null)
            {
                ValueProviderResult valueProviderResult = valueProviderCollection.GetValue(bindingContext.ModelName, skipValidation: true);
                bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            }

            string errorMessage = string.Format(CultureInfo.CurrentCulture, "{0} contains invalid symbols: <, &",
                     bindingContext.ModelMetadata.DisplayName);

            bindingContext.ModelState.AddModelError(bindingContext.ModelName, errorMessage);
        }
    }

In Application_Start:

ModelBinders.Binders.DefaultBinder = new AppModelBinder();

Note that it works only for form fields. Dangerous value not passed to controller model, but stored in ModelState and can be redisplayed on form with error message.

Dangerous chars in URL may be handled this way:

private void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    HttpContext httpContext = HttpContext.Current;

    HttpException httpException = exception as HttpException;
    if (httpException != null)
    {
        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Error");
        var httpCode = httpException.GetHttpCode();
        switch (httpCode)
        {
            case (int)HttpStatusCode.BadRequest /* 400 */:
                if (httpException.Message.Contains("Request.Path"))
                {
                    httpContext.Response.Clear();
                    RequestContext requestContext = new RequestContext(new HttpContextWrapper(Context), routeData);
                    requestContext.RouteData.Values["action"] ="InvalidUrl";
                    requestContext.RouteData.Values["controller"] ="Error";
                    IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
                    IController controller = factory.CreateController(requestContext, "Error");
                    controller.Execute(requestContext);
                    httpContext.Server.ClearError();
                    Response.StatusCode = (int)HttpStatusCode.BadRequest /* 400 */;
                }
                break;
        }
    }
}

ErrorController:

public class ErrorController : Controller
 {
   public ActionResult InvalidUrl()
   {
      return View();
   }
}   

Use the Server.HtmlEncode("yourtext");

For those of us still stuck on webforms I found the following solution that enables you to only disable the validation on one field! (I would hate to disable it for the whole page.)

VB.NET:

Public Class UnvalidatedTextBox
    Inherits TextBox
    Protected Overrides Function LoadPostData(postDataKey As String, postCollection As NameValueCollection) As Boolean
        Return MyBase.LoadPostData(postDataKey, System.Web.HttpContext.Current.Request.Unvalidated.Form)
    End Function
End Class

C#:

public class UnvalidatedTextBox : TextBox
{
    protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
    {
        return base.LoadPostData(postDataKey, System.Web.HttpContext.Current.Request.Unvalidated.Form);
    }
}

Now just use <prefix:UnvalidatedTextBox id="test" runat="server" /> instead of <asp:TextBox, and it should allow all characters (this is perfect for password fields!)

Not the answer you're looking for? Browse other questions tagged or ask your own question.