0

I have overridden OnError method in the page:

public string script;

    protected override void OnError(EventArgs e)
    {
        script = "alert('error');";
    }

In the aspx, I have this:

<script type="text/javascript">
$(document).ready(function(){
        <%=script  %>;
    });
</script>

I am simulating an error in Page_Load, but its not firing the alert. If I switch the code from OnError to OnLoad, it works great.

Thoughts?

Kristijan Iliev
  • 4,901
  • 10
  • 28
  • 47
Dusty
  • 2,159
  • 3
  • 23
  • 26

4 Answers4

1

When you override OnError, you need to clear the error so you mark it as handled, if you don't do this then it will bubble up to Application_Error, trashing any content your page may have rendered..

Try using Server.ClearError

protected override void OnError(EventArgs e)     
{         
   script = "alert('error');";
   Server.ClearError(); //Prevent the error from propagating     
}

Looking in reflector you can see this..

try
{
    this.Context.TempError = e;
    this.OnError(EventArgs.Empty);
    if (this.Context.TempError == null)
    {
        return true;
    }
}
finally
{
    this.Context.TempError = null;
}

Server.ClearError clears that TempError

public void ClearError()
{
    if (this._tempError != null)
    {
        this._tempError = null;
    }
   ...other code..
 }
Richard Friend
  • 15,800
  • 1
  • 42
  • 60
  • My issue is not with the Application_Error being called. Infact, I require it to be called as I do some logging there. All I want to do is to call a JS function before propogating – Dusty Apr 01 '11 at 15:11
  • If you let it bubble up to Application_Error, then use Server.ClearError inside there - if you read the link it explains. – Richard Friend Apr 01 '11 at 15:14
  • I used the `Server.ClearError` as you demonstrate. The JS function still doesn't get called and now I see a blank page instead of the error details and the stack trace – Dusty Apr 01 '11 at 15:22
0

Because the page isn't erroring and so the OnError event isn't being fired.

Or are you forcing the error and the alert still isn't showing?

By the way, take out the tags in the script insertion, and just have the alert - you already have the defined in your ASPX.

Update:

It's likely to do with the hierarchy of calls, the document.ready() is being called BEFORE the OnError is happening.

Try putting the whole thing into a literal, such as:

<asp:Literal runat="server" ID="JScript" />

    protected override void OnError(EventArgs e)
        {
            JScript.Text = "<script type=\"text/javascript\">alert('error');</script>";
        }
Chris Dixon
  • 9,147
  • 5
  • 36
  • 68
  • Yes, I am throwing an error `throw new ApplicationException()` – Dusty Apr 01 '11 at 14:24
  • Is the OnError being called at all? Have you put a breakpoint on the line to see if the line is firing? – Chris Dixon Apr 01 '11 at 14:27
  • @thedixon - Yes, the OnError does get called, the very next thing that happens is the Application_Error in the Global.asax.cs and it never fires that alert – Dusty Apr 01 '11 at 14:32
  • Updated my answer - something for you to try. – Chris Dixon Apr 01 '11 at 14:52
  • @thedixon: If he's throwing an `ApplicationException` in `Page_Load`, how could `document.ready` be happening before `OnError`? – Town Apr 01 '11 at 14:57
  • I've seen stranger things happen with code... and there's not many other logical reasonings that I can see for the lack of the alert calling, other than the event hierarchy. – Chris Dixon Apr 01 '11 at 15:00
  • @thedixon: I've never seen anything stranger than that. That would be client-side code executing before server-side code. – Town Apr 01 '11 at 15:16
  • Client side code DOES execute before server side code... you can see that easily with OnClientClick events. – Chris Dixon Apr 01 '11 at 15:34
  • @Dusty: Also, don't use ApplicationException, [it's considered obsolete](http://stackoverflow.com/questions/52753/should-i-derive-custom-exceptions-from-exception-or-applicationexception-in-net). – Town Apr 01 '11 at 20:53
0

What you are doing would result in code like this in the output page:

<script type="text/javascript">
$(document).ready(function(){
   <script language='javascript' type='text/javascript'>alert('error')</script>;
});
</script>

which is obviously wrong. You need to change the script variable to:

script = @"alert('error')";
paracycle
  • 7,665
  • 1
  • 30
  • 34
  • @paracyle - Hmm Good catch, let me try that. Although it doesn't explain why the exact same script works on a different page event other than `OnError` – Dusty Apr 01 '11 at 14:25
  • No, making that change didn't help – Dusty Apr 01 '11 at 14:31
  • What do you get in the browser when this happens? Does the page load at all? – paracycle Apr 01 '11 at 14:34
  • The OnError gets fired, and then the Application_Error in global.asax.cs and then it shows the error on the page (with stack trace) but never fires the alert. – Dusty Apr 01 '11 at 14:40
  • @Dusty: It doesn't fire the alert because the `Exception` isn't handled and `Render` never runs. – Town Apr 01 '11 at 15:19
0

The fact that you're throwing an Exception and not handling it in the page with a try/catch means that the page never finishes rendering. Not only are you not getting the output of your script string, you'll probably find you're not getting the $(document).ready() or anything else either as the page isn't rendering.

If you handle the exception like this then the page rendering will complete and your message will display.

try
{
    throw new Exception();
}
catch(Exception ex)
{
    // log ex.ToString() here
    script = "alert('error')";
    // decide what to do here - carry on or return
}

In real terms you should try to avoid catching Exception, always try to anticipate which specific exceptions you expect and handle them accordingly. In fact, always try to avoid cases where an Exception can be thrown in the first place - Exceptions should be thrown in exceptional circumstances.

Have a read through this CodeProject article that discusses some best practices regarding exception handling.

Town
  • 14,706
  • 3
  • 48
  • 72
  • This solution sounded promising. Unfortunately, I can't get this to work. The alert never happens. Any thoughts? – Dusty Apr 01 '11 at 15:27
  • @Dusty: I built a test project, that works. Have you definitely got a reference to jQuery? – Town Apr 01 '11 at 15:43
  • That worked! But I am far from being done with this issue. Basically, the example I provided is a trivial example pulled from a larger framework. The framework I have is a page that _hosts_ a user control (by doing a `LoadControl`). I need to ensure that _any_ error from the user control should trigger this JS function. This can include Page Load, Prerender, Oninit or any of those methods. I can't really have `try..catch` blocks everywhere. Also I have atleast 10 user controls that can be loaded. So, I really dont want to update all these controls' page events to include try catch. – Dusty Apr 01 '11 at 15:59
  • Also the second issue is that this solution only works if you dont `throw` after the `script = ..`. But I need these errors to go through the `Application_Error` to do the logging. – Dusty Apr 01 '11 at 16:01
  • @Dusty: You should be handling the exceptions that get returned from the user controls at the point you load them, using try/catch. You can then log with a logging library such as Log4Net, write to a log file/database or whatever you need to do whilst continuing normal operation. If one failing user control puts the application into an unusable state, then bubble the exception upwards and use [Custom Error Pages](http://www.asp.net/hosting/tutorials/displaying-a-custom-error-page-cs) to display a message. – Town Apr 01 '11 at 20:35