Delphi Clinic C++Builder Gate Training & Consultancy Delphi Notes Weblog Dr.Bob's Webshop
Dr.Bob's Delphi Notes Dr.Bob's Delphi Clinics Dr.Bob's Delphi Courseware Manuals
 Dr.Bob Examines... #73
See Also: other Dr.Bob Examines columns or Delphi articles

This article is based on a post in my weblog.

HttpRequestValidationException
How to handle “dangerous” HTML input in ASP.NET web forms

ASP.NET 1.1 has this nice "feature" of automatically validating the incoming Request (QueryString, Form and Cookies) to prevent script attacks.This new validation code will raise an HttpRequestValidationException, which will be raised before the OnInit itself is executed.

Demo Example
As an example, let’s use Delphi or any other ASP.NET supporting development environment to create a new ASP.NET application.
Place a TextBox, a Button and another TextBox control (the second one with the TextMode property set to MultiLine).

To complete the example, let’s add a single line of code to the Click event of the Button, as follows:

  procedure TWebForm1.Button1_Click(sender: System.Object;
    e: System.EventArgs);
  begin
    TextBox2.Text := TextBox2.Text + #13#10 + TextBox1.Text;
  end;
If we compile and run the project, the result is a nice little ASP.NET application that can be used to add single line entries from the first TextBox to the multi-line contents of the second TextBox. So far, so good, and you can add just about any text you wish.Just about, since not everything is possible.If you try to add a little decoration to the input string, for example using HTML tags like and then all of a sudden we get a not so nice message from the ASP.NET environment, telling us that HTML tags are considered potentially dangerous, and a potentially dangerous Request.Form value was detected from the client, namely
  “TextBox1=”Test met bold”.

The problem I have with that, is the fact that the resulting error message is not very nice. And although I could define a custom error page, I'd much rather give the user a friendly reminder that HTML is not allowed as normal ASP.NET input. Of course, I could turn the validation off, by specifying validateRequest="false" in the Page directive of my ASP.NET page, but I don't really want to do that, since that would open up my ASP.NET page for some actual (and potentially more serious) script attacks.There’s a reason this validation exists, so we should not disable it just because it’s inconvenient.

First Attempt to Catch The Error
If you try to trace of debug this application, you will find that it’s not possible to catch an exception in your Page events, since the exception itself is raised before we can assign an event handler to the Self.Error property in the InitalizeComponents routine. In my weblog at http://www.drbob42.com/blog I describe a technique where I wanted to make sure the Error event of my ASP.NET page was assigned before the validation is raising an exception.To do this, I declared a constructor, and set the Error event manually (since the assignment in the InitializeComponents would be too late).In effect, I ended up with the following code:

  constructor TWebForm1.Create;
  begin
     inherited;
     Include(Self.Error, Self.TWebForm1_Error)
  end;
And then in the Error handler I cleared the error and set the StatusCode back to 200, as follows:
  procedure TWebForm1.TWebForm1_Error(sender: System.Object;
    e: System.EventArgs);
  begin
     if (Server.GetLastError.GetBaseException is System.Web.HttpRequestValidationException) then
     begin
        Response.Clear;
        Response.Write('Sorry, not HTML allowed...');
        Response.StatusCode := 200;
        Response.&End
     end
  end;

Second Way to Catch The Error
However, instead of doing it this way, we can also simply override the OnError method, and prepare to handle the error in that method. To implement the new solution (instead of the constructor and TWebForm1_Error method as described above), place your cursor inside the TWebForm1 class, press Ctrl+Space which will present you with the list of methods from the System.Web.UI.Page base class which we can override.Select the OnError method and press enter.Next, press Ctrl+C to generate the implementation for the OnError method, and implement it as follows:

  procedure TWebForm1.OnError(e: EventArgs);
  begin
    inherited;
    if (Server.GetLastError.GetBaseException is
        System.Web.HttpRequestValidationException) then
    begin
       Response.Write('Sorry, not HTML allowed...');
       Response.StatusCode := 200;
       Response.&End
    end
  end;

Nicer Way to Catch The Error
This still results in an error page (a bit nicer), and not my original page.So, I had to add a little trick to it, redirecting to the original page with an additional queryfield, so I can give a nice error message (and still show the original page).

  procedure TWebForm1.OnError(e: EventArgs);
  begin
    if (Server.GetLastError.GetBaseException is
        System.Web.HttpRequestValidationException) then
    begin
      Response.StatusCode := 200;
      Response.Redirect(Request.Url.ToString + '?Ex=42', True)
    end
  end;
Note that the second argument to the Response.Redirect specifies if this means the end of the response, so we do not have to explicitly call Response.End again. In the Page_Load, I can now check for the Request.Params['Ex'] to see if an error was raised, so I should give the user a friendly error message instead.
      if Request.Params['Ex'] = '42' then
         Response.Write('Sorry. no HTML allowed here!');
Instead of using the low-level Response.Write you can also use a Label and set the Text here.What matters is that you tell the user that HTML is not allowed, and give the user a chance to re-enter the text.

Summary
In this short article, I’ve shown you a simple technique that will leave ASP.NET input validation (and script detection) intact, but will respond with a more friendly error message for the HttpRequestValidationException in case your visitors enter HTML or related text in your ASP.NET web forms. Note that the contents which was entered in the “invalid” request is gone, but so is the contents of the multi-line TextBox, since we did a Response.Redirect, so the entire ViewState is gone! But at least it’s better than the ugly error message we saw before.


This webpage © 2006-2010 by Bob Swart (aka Dr.Bob - www.drbob42.com). All Rights Reserved.