views:

764

answers:

8

I'm trying to override the onError event handler of a web form to allow "A potentially dangerous Request.Form value was detected from the client" type errors to be handled within the form rather than ending up at the application level error handler.

I found some sample code like this :

   protected override void OnError(EventArgs e)
{
    // At this point we have information about the error
    HttpContext ctx = HttpContext.Current;

    Exception exception = ctx.Server.GetLastError();

    string errorInfo =
       "<br>Offending URL: " + ctx.Request.Url.ToString() +
       "<br>Source: " + exception.Source +
       "<br>Message: " + exception.Message +
       "<br>Stack trace: " + exception.StackTrace;

    ctx.Response.Write(errorInfo);

    // --------------------------------------------------
    // To let the page finish running we clear the error
    // --------------------------------------------------
    ctx.Server.ClearError();

    base.OnError(e);

}

Which satisfactorily catches the error and writes an error message out to the screen but what I really want to do is to be aware of the error when Page_Load fires and so be able to display a 'normal' error message on the webform.

I'm sure there's a good way to do this but I don't know it ! Suggestions ?

(BTW for various reason I don't want to turn off the checking at either form or app level and neither do I wish to rely on Javascript - thanks)

A: 

Just a suggestion, but can you capture it in the Page_Init event handler instead?

Scott Ferguson
Thanks for the idea. I tried it but when the "A potentially dangerous Request.Form value was detected from the client" type error is being raised you Page_Init never fires.
southof40
A: 

[Just repeating this as an answer ... didn't realise comments were quite so hard to see]

Just a suggestion, but can you capture it in the Page_Init event handler instead?

Thanks for the idea. I tried it but when the "A potentially dangerous Request.Form value was detected from the client" type error is being raised you Page_Init never fires.

southof40
A: 

@Fistandantilus thanks for your response. Because of where this error gets generated the only place in the Web Form that gets to 'see' the error is an overridden OnError method. Page_Load for instance is never executed when this error has been raised. I'm really looking for the best way to detect and clear the error in OnError but then able to do something about it Page_Load (hmmm for some reason I've got lot of italics in this response which I didn't want so please ignore them ! )

southof40
A: 

I don't think you'll be able to handle the error in the Page_load event. In the ASP.NET Page Life cycle validation events occur after the page loads.

Maybe you can add a hidden div (<asp:Panel Visible=false ...) that contains your "normal error message". if the OnError event fires display the error message div.

jason

Jason
A: 

@Jason thanks for your reply. I'm not terribly knowledgeable about this myself but the type of error we're seeing here (essentially an attempt by MS to stop XSS exploits) is raised before Page_Load is fired and in face Page_Load never fires (at least when an application level error handler is in place) when this type of error has been fired.

What's needed (it seems to me) is some way to register the state of the error having been fired but in such a way that normal processing takes place so Page_Load can setup an error message.

I'm sure there's a very standard way of doing this ???

southof40
+1  A: 

I think I understand what you want to do, but I'm afraid it might be impossible. When your ASP.NET page performs a postback, a new thread is created on the server to handle the request. Before your page lifecycle even has a chance to begin, the offending XSS is found and an exception is thrown. Once this exception is thrown, you are "evicted" from the ASP.NET page lifecycle and there is no way to re-enter it. At this point, the only thing you can do on the client side is output the error, or redirect to an error page.

What you seem to want to do is catch the exception, write it out somewhere on the page, and continue with the ASP.NET page lifecycle (i.e. restoring the control tree, restoring viewstate, invoking event handlers, etc). The problem is once an unhandled exception is thrown you no longer have access to the ASP.NET page lifecycle. In this particular case, there is nowhere to put a try/catch block because the exception is thrown internally from the ASP.NET lifecycle before your own code is called.

I know you said you don't want to rely on Javascript, but in this case I think using Javascript is the only way to get the behavior you want. You can still keep server-side validation, just in case your users disable Javascript or type some input that your Javascript doesn't handle.

davogones
+1  A: 

You actually can catch the error at the page level, but it will kill the page lifecycle. So you have to use a trick to get around it. Example:

public override void ProcessRequest(HttpContext context)
{
  try
  {
    base.ProcessRequest(context);
  }
  catch(HttpRequestValidationException ex)
  {
      context.Response.Redirect("HandleValidationError.aspx");
  }
}

HandleValidationError.aspx can be anything, including a redirection back to the same page (perhaps with a querystring with information regarding the error, e.g. "ContactForm.aspx?error=Invalid+Request")

Keltex
A: 

Thanks to all for interesting responses.

southof40