How to make Elmah work with UnobservedTaskException - c#

I'm developing a asp.net mvc application. The architecture of my application as below:
a DBAccessLayer //layer for accessing database
a ServiceLayer //layer to connect 1 and 3.
a WebLayer //Web UI layer
I want to log all application exceptions including the exceptions in the TaskScheduler.UnobservedTaskException event.
I've tested to do as below:
protected void Application_Start()
{
...
TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs excArgs) =>
{
ErrorSignal.FromCurrentContext().Raise(excArgs.Exception);
excArgs.SetObserved();
};
}
but when the UnobservedTaskException event is fired, the application crashed with exception as below:
System.ArgumentNullException was unhandled
Message=Value cannot be null.
Parameter name: context
Source=Elmah
ParamName=context
StackTrace:
at Elmah.ErrorSignal.FromContext(HttpContext context) in c:\builds\ELMAH\src\Elmah\ErrorSignal.cs:line 67
at MyMvcApplication.<Application_Start>b__0(Object sender, UnobservedTaskExceptionEventArgs excArgs) in ...\Global.asax.cs:line 82
at System.Threading.Tasks.TaskScheduler.PublishUnobservedTaskException(Object sender, UnobservedTaskExceptionEventArgs ueea)
at System.Threading.Tasks.TaskExceptionHolder.Finalize()
Additionally, I put the UnobservedTaskException event in the global.asax.cs of WebLayer, can it be fired when the DBAccessLayer and ServiceLayer have unobserved exceptions?
Thanks.

It looks like when your handler gets fired, there isn't an HttpContext because the scheduled task is not running as part of an HTTP request. Instead of using
ErrorSignal.FromCurrentContext().Raise
you could use
ErrorLog.GetDefault(null).Log

Related

CurrentDomain.UnhandledException is not being thrown in Windows Service

I've setup the UnhandledException to log any exceptions before my service crashes.
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(unhandledException);
I'm testing this by throwing and unhandled exception.
throw new Exception("TestExcepion");
private void unhandledException(object sender, UnhandledExceptionEventArgs e)
{
// Logs to Log4Net but its not reaching here.
Log.Info("Unhandled Exception: " + (e.ExceptionObject as Exception).ToString());
}
I'm attempting to log this within my unhandledException method using Log4Net but im getting nothing.
Why isn't the exception being caught?
It is probably that your throwing code is before use set AppDomain.CurrentDomain.UnhandledException or because you put it in OnStart method
Second option is because it is ThreadException.
Bot above problems were discussed before in following threads:
How can I set up .NET UnhandledException handling in a Windows service?
Global exception handler for windows services?

AppDomain.CurrentDomain.UnhandledException does not get called

I have a WCF service that has the following code in Global.asax:
protected void Application_Start(object sender, EventArgs e)
{
// Make sure that any exceptions that we don't handle at least get logged.
AppDomain.CurrentDomain.UnhandledException += LogUnhandledException;
}
private void LogUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Log.Error.LogException("UnhandledException", e.ExceptionObject as Exception);
}
The idea is to at least log all exceptions that are unhanded.
But it does not seem to ever be called. I tried doing a Divide by Zero in one of my service operations and it just stops the service after it hits the exception.
int zero = 0;
int result = 100 / zero;
The LogUnhandledException method never gets called.
I have tried this in both IIS and running in the debugger.
How can I get this event to work for a WCF service?
The unhandled exception filter for an app domain is a last-ditch attempt to allow the application to log meaningful information before it is terminated.
This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application.
If WCF allowed an exception thrown by a service to be completely unhandled in this way it would mean that when the service is hosted in IIS the entire worker process would be terminated because a single request raised an exception - not a desirable outcome. As a result WCF doesn't leave exceptions thrown by services unhandled - this event will not be raised in this case.
If you want to log exceptions thrown by WCF services then take a look at the IErrorHandler interface instead.
Try also catching a ThreadException, e.g.
Application.ThreadException += Application_ThreadException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
I had the same issue in the WinForms app a while ago. UnhandledException is raised for truly unhandled exceptions that would normally terminate your entire process immediately. Typically there's a global handler that doesn't let that happen, and provides some default behavior. So you need to catch the exception before it goes to that handler. This can be done via a ThreadException.
Have you tried this?
From http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(LogUnhandledException);
I'm wondering what is difference between your call and this one, with the "+= new"... but it's worth the try.

App enters unknown/locked state after handling UnhandledException

In my App.xaml.cs I have events to handle DispatcherUnhandledExceptions (UI thread) and UnhandledException (Non UI thread). When I throw an exception inside dispatcher.Invoke, the dispatcherhandler catches the exception and handles it. I am setting e.Handled to true after logging the exception. Now the strange behaviour, if i throw the exception outside of the dispatcher.Invoke as a regualr statment, control is sent to the dispatcher exception handler,but after the method is processed the app basically loses control but I can tell its still running by looking at the stop button in vs.
one more thing, if i set e.handled to false, control is sent to the non-ui thread exception handler.
So what puzzles me is why is the application locking after handling the exceptiono in the dispatcher handler?
here's my code
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
// log exception here
e.Handled = true;
} // control is lost after executing this block
private void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
Exception ex = e.ExceptionObject as Exception;
// log exception here
}
finally
{
Environment.Exit(-1);
}
}
An UnhandledException means that your application is effectively dead. If you get that event then it is too late to do anything to recover from the scenario. Typically you would use this event only to log errors for debugging purposes and maybe attempt to cleanup some unmanaged resources.
The following article gives a detailed explanation of exception handling in WPF.
It seems like the app is able to resume operation if the exception is raised after the OnStartup Event, if the exception is raised in between, the exception is caught and handled but the main window is never shown yet the debugger shows the app as running.
the closest solution I found is to remove complex logic from the constructor of main window to allow onstartup event to execute and do a lot of loading in my MainWindow load event.

Catching Exceptions in WPF at the FrameWork Level

I'm developing a light-weight WPF MVVM framework, and would like to be able to catch unhandled exceptions, and ideally recover from them.
Ignoring for the moment all the good arguments for not doing this, I encounter the following situation:
If I register a handler for AppDomain.CurrentDomain.UnhandledException within the OnStartup method of the App.xaml.cs, as follows...
App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += new
UnhandledExceptionEventHandler(this.AppDomainUnhandledExceptionHandler);
base.OnStartup(e);
}
void AppDomainUnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs ea)
{
Exception e = (Exception)ea.ExceptionObject;
// log exception
}
and then raise an exception within one of my VM's, the handler is called as expected.
So far so good, except for the fact that there is no way that I can recover using this approach, all that I can do is log the exception and then let the CLR terminate the app.
What I actually wanted to do is to recover, and return control to the main framwork VM. (Again putting aside the motivations against doing this).
So, doing some reading, I decide to register an event handler for AppDomain.CurrentDomain.UnhandledException in the same place, so that the code now looks something like this...
protected override void OnStartup(StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(this.AppDomainUnhandledExceptionHandler);
this.DispatcherUnhandledException +=
new DispatcherUnhandledExceptionEventHandler(DispatcherUnhandledExceptionHandler);
base.OnStartup(e);
}
void AppDomainUnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs ea)
{
Exception e = (Exception)ea.ExceptionObject;
// log exception
}
void DispatcherUnhandledExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs args)
{
args.Handled = true;
// implement recovery
}
The issue is that once I register the handler for this.DispatcherUnhandledException, NEITHER EVENT HANDLER IS CALLED. So registering the DispatcherUnhandledExceptionHandler somehow deactivates the handler for AppDomain.CurrentDomain.UnhandledException.
Does anyone have an approach for catching and recovering from unhandled VM exceptions ?
It might be important to mention that there is no explicit use of threading in the framework.
The reason VS shows you the exception is because you have set it up like that (either you did this explicitly or - more likely - the defaults in VS configured it like this). You can control what Visual Studio does when it encounters an exception in the debugged code through the Debug->Exceptions menu.
You can even make it break even though you have a catch for it which is quite handy in some cases.
If you're not using multi threading then you should be fine with the DispatcherUnhandledException event since it will catch everything that gets uncaught on the main UI thread.
A quick answer to my own question:
This works...
App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
Application.Current.DispatcherUnhandledException +=
new DispatcherUnhandledExceptionEventHandler(DispatcherUnhandledExceptionHandler);
base.OnStartup(e);
}
void DispatcherUnhandledExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs args)
{
args.Handled = true;
// implement recovery
// execution will now continue...
}
[Edit: My comments below have nothing to with the implementation, but my specific IDE (Visual Studio) config with respect to exception catching by the IDE. Please see Isak's comments above.]
BUT, and it's a big but, if you're executing from within VisualStudio, then YOU WILL STILL GET THE VS exception notification dialog box popping up, and the DispatcherUnhandledExceptionHandler will only be invoked if you press F5/continue, after which execution will continue as per normal.
If you're running the compiled binary directly, i.e from the command line or via Windows Explorer, then the handler will be invoked as you would expect, without any intermediary popup.

ASP.NET Global.asax Application_Error works but not when using the Error event

I have an ASP.NET MVC application that is supposed to catch all unhandled exceptions within the global.asax application error handler.
If I define the handler as follows:
protected void Application_Error(object sender, EventArgs e)
then it works fine. However, if within the Application_Start event I try and do:
this.Error += new EventHandler(Application_Error);
The actual event is never called.
Does anyone know why and if so what i'm doing incorrectly?
You shouldn't have to add to the error event explicitly; Application_Error should get called automatically by the framework.
The event is not being called either because Exceptions are being caught somewhere else in the application (and swallowed maybe) or because you are registering the event in the Application_Start event (not needed). You want to do something like this in your Application_Error:
protected void Application_Error(object sender, EventArgs e) {
Exception exception = Server.GetLastError();
// log exception
// Email exception
}
I use this method to both log and E-mail uncaught errors for all my applications. Hope this helps.

Categories