.Net - What's the Best Way to Implement a "Catch All Exceptions Handler"

.NET - What's the best way to implement a catch all exceptions handler

I have just played with AppDomain's UnhandledException behavior,
(this is the last stage the unhandled exception is registered at)

Yes, after processing the event handlers your application will be terminated and the nasty "... program stopped working dialog" shown.

:)
You still can avoid that.

Check out:

class Program
{
void Run()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

Console.WriteLine("Press enter to exit.");

do
{
(new Thread(delegate()
{
throw new ArgumentException("ha-ha");
})).Start();

} while (Console.ReadLine().Trim().ToLowerInvariant() == "x");

Console.WriteLine("last good-bye");
}

int r = 0;

void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Interlocked.Increment(ref r);
Console.WriteLine("handled. {0}", r);
Console.WriteLine("Terminating " + e.IsTerminating.ToString());

Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Dead thread";

while (true)
Thread.Sleep(TimeSpan.FromHours(1));
//Process.GetCurrentProcess().Kill();
}

static void Main(string[] args)
{
Console.WriteLine("...");
(new Program()).Run();
}
}

P.S. Do handle the unhandled for Application.ThreadException (WinForms) or DispatcherUnhandledException (WPF) at the higher level.

ASP.NET C# Catch all exceptions in a class

Yes it is. The simplest way would be a Attribute for this class like this one:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class HandleErrorAttribute : FilterAttribute, IExceptionFilter
{

public void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}

if (filterContext.ExceptionHandled)
{
return;
}

var exception = filterContext.Exception;

// that need to be your current request object. In this case I use a custom one so I must fetch it from the items collection of the current request, where I had stored it before.
var request = filterContext.HttpContext.Items[Request.RequestKey] as Request;

if (request != null)
{
// overwrite ErrorResponse with a response object of your choice or write directly to the filterContext.HttpContext.Response
var errorResponse = new ErrorResponse(request, exception);
errorResponse.Write(filterContext.HttpContext.Response);
filterContext.ExceptionHandled = true;
}
}
}

// Or a just slightly modified version of the default ASP.Net MVC HandleError Attribute
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CustomHandleErrorAttribute : FilterAttribute, IExceptionFilter
{
// Fields
private const string _defaultView = "Error";
private string _master;
private readonly object _typeId = new object();
private string _view;

// Methods
public virtual void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (!filterContext.IsChildAction && (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled))
{
Exception innerException = filterContext.Exception;
if ((new HttpException(null, innerException).GetHttpCode() == 500))
{
string controllerName = (string)filterContext.RouteData.Values["controller"];
string actionName = (string)filterContext.RouteData.Values["action"];
HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
ViewResult result = new ViewResult();
result.ViewName = this.View;
result.MasterName = this.Master;
result.ViewData = new ViewDataDictionary<HandleErrorInfo>(model);
result.TempData = filterContext.Controller.TempData;
filterContext.Result = result;
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusCode = 500;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
}
}
}

public string Master
{
get
{
return (this._master ?? string.Empty);
}
set
{
this._master = value;
}
}

public override object TypeId
{
get
{
return this._typeId;
}
}

public string View
{
get
{
if (string.IsNullOrEmpty(this._view))
{
return "Error";
}
return this._view;
}
set
{
this._view = value;
}
}
}

Usage (untested cause I used it in context of controller that already implement all required interfaces)

[HandleErrorAttribute]
public class Foo : IExceptionFilter // (I am not sure about this one IActionFilter)
{

public void MethodA()
{
// body
}

public void MethodB()
{
// body
}

public void MethodC()
{
// body
}

}

Or you can do something like this:

public class ExecuteHelper
{
public static void Catch(Action action)
{
try
{
action();
}
catch (Exception ex)
{
// Do what you want
}
}
}

And use it in a Function body:

public void Foo(string something)
{
ExecuteHelper.Catch(() =>
{
// Do something with something or without something
});
}

How using try catch for exception handling is best practice

My exception-handling strategy is:

  • To catch all unhandled exceptions by hooking to the Application.ThreadException event, then decide:

    • For a UI application: to pop it to the user with an apology message (WinForms)
    • For a Service or a Console application: log it to a file (service or console)

Then I always enclose every piece of code that is run externally in try/catch :

  • All events fired by the WinForms infrastructure (Load, Click, SelectedChanged...)
  • All events fired by third party components

Then I enclose in 'try/catch'

  • All the operations that I know might not work all the time (IO operations, calculations with a potential zero division...). In such a case, I throw a new ApplicationException("custom message", innerException) to keep track of what really happened

Additionally, I try my best to sort exceptions correctly. There are exceptions which:

  • need to be shown to the user immediately

  • require some extra processing to put things together when they happen to avoid cascading problems (ie: put .EndUpdate in the finally section during a TreeView fill)

  • the user does not care, but it is important to know what happened. So I always log them:

  • In the event log

  • or in a .log file on the disk

It is a good practice to design some static methods to handle exceptions in the application top level error handlers.

I also force myself to try to:

  • Remember ALL exceptions are bubbled up to the top level. It is not necessary to put exception handlers everywhere.
  • Reusable or deep called functions does not need to display or log exceptions : they are either bubbled up automatically or rethrown with some custom messages in my exception handlers.

So finally:

Bad:

// DON'T DO THIS; ITS BAD
try
{
...
}
catch
{
// only air...
}

Useless:

// DON'T DO THIS; IT'S USELESS
try
{
...
}
catch(Exception ex)
{
throw ex;
}

Having a try finally without a catch is perfectly valid:

try
{
listView1.BeginUpdate();

// If an exception occurs in the following code, then the finally will be executed
// and the exception will be thrown
...
}
finally
{
// I WANT THIS CODE TO RUN EVENTUALLY REGARDLESS AN EXCEPTION OCCURRED OR NOT
listView1.EndUpdate();
}

What I do at the top level:

// i.e When the user clicks on a button
try
{
...
}
catch(Exception ex)
{
ex.Log(); // Log exception

-- OR --

ex.Log().Display(); // Log exception, then show it to the user with apologies...
}

What I do in some called functions:

// Calculation module
try
{
...
}
catch(Exception ex)
{
// Add useful information to the exception
throw new ApplicationException("Something wrong happened in the calculation module:", ex);
}

// IO module
try
{
...
}
catch(Exception ex)
{
throw new ApplicationException(string.Format("I cannot write the file {0} to {1}", fileName, directoryName), ex);
}

There is a lot to do with exception handling (Custom Exceptions) but those rules that I try to keep in mind are enough for the simple applications I do.

Here is an example of extensions methods to handle caught exceptions a comfortable way. They are implemented in a way they can be chained together, and it is very easy to add your own caught exception processing.

// Usage:

try
{
// boom
}
catch(Exception ex)
{
// Only log exception
ex.Log();

-- OR --

// Only display exception
ex.Display();

-- OR --

// Log, then display exception
ex.Log().Display();

-- OR --

// Add some user-friendly message to an exception
new ApplicationException("Unable to calculate !", ex).Log().Display();
}

// Extension methods

internal static Exception Log(this Exception ex)
{
File.AppendAllText("CaughtExceptions" + DateTime.Now.ToString("yyyy-MM-dd") + ".log", DateTime.Now.ToString("HH:mm:ss") + ": " + ex.Message + "\n" + ex.ToString() + "\n");
return ex;
}

internal static Exception Display(this Exception ex, string msg = null, MessageBoxImage img = MessageBoxImage.Error)
{
MessageBox.Show(msg ?? ex.Message, "", MessageBoxButton.OK, img);
return ex;
}

Catching all exceptions on a site the best way

Add Global.asax file to your asp.net project and handle application error:

    void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
string errorMessage = "Application Exception: " + ex.Message;
if (ex.InnerException != null)
{
errorMessage += Environment.NewLine + "Inner Exception: " + ex.InnerException.Message;
}
if (Context != null && Context.Request != null)
{
errorMessage += Environment.NewLine + "Absolute Url: " + Context.Request.Url.AbsolutePath;
}
Services.LoggerManager.Log(
Services.LoggerManager.eLogContext.Application,
Services.LoggerManager.eLogType.Error,
Context, errorMessage);
}

And here is LoggerManager part:

public static class LoggerManager
{

public enum eLogType
{
Information = 0,
Warning = 1,
Error = 2
}

public enum eLogContext
{
Application = 0,
Session = 1
}

/// <summary>
/// Method for logging custom message
/// </summary>
/// <param name="logContext"></param>
/// <param name="logType"></param>
/// <param name="context"></param>
/// <param name="message"></param>
public static void Log(eLogContext logContext, eLogType logType, HttpContext context, string message)
{
switch (logContext)
{
case eLogContext.Application:
//TODO: log application type event...
break;
case eLogContext.Session:
//TODO: log session type event...
break;
default:
throw new NotImplementedException("eLogContext '" + logContext.ToString() + "' is not implemented!");
}
}

}

Should you catch all exceptions?

Only catch the ones that make sense to handle for the level of abstraction at which you are writing the code. Most exceptions will only be caught at a much higher level than where they are thrown.

So yes, you are correct. :)

catch all unhandled exceptions in ASP.NET Web Api

This is now possible with WebAPI 2.1 (see the What's New):

Create one or more implementations of IExceptionLogger. For example:

public class TraceExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
Trace.TraceError(context.ExceptionContext.Exception.ToString());
}
}

Then register with your application's HttpConfiguration, inside a config callback like so:

config.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());

or directly:

GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());

How to catch ALL exceptions/crashes in a .NET app

Contrary to what some others have posted, there's nothing wrong catching all exceptions. The important thing is to handle them all appropriately. If you have a stack overflow or out of memory condition, the app should shut down for them. Also, keep in mind that OOM conditions can prevent your exception handler from running correctly. For example, if your exception handler displays a dialog with the exception message, if you're out of memory, there may not be enough left for the dialog display. Best to log it and shut down immediately.

As others mentioned, there are the UnhandledException and ThreadException events that you can handle to collection exceptions that might otherwise get missed. Then simply throw an exception handler around your main loop (assuming a winforms app).

Also, you should be aware that OutOfMemoryExceptions aren't always thrown for out of memory conditions. An OOM condition can trigger all sorts of exceptions, in your code, or in the framework, that don't necessarily have anything to do with the fact that the real underlying condition is out of memory. I've frequently seen InvalidOperationException or ArgumentException when the underlying cause is actually out of memory.

What's the best way to handle the exceptions and how to deal with them in asp.net

Exception handling is a big deal, and it's not simple to design a good strategy for that.

First of all, some general rules:

  • Exceptions occur when the running code is completely unable to go ahead, so maybe it tried to handle some internal exceptions but ultimately failed. Think about TCP connection: if a damaged packet arrives, it's an exception, but TCP protocol can handle it. If too many are damaged, an I/O or socket exception is thrown
  • Exceptions can not always be handled. In almost all cases, when you get an exception from underlying layers you are unable to run corrective code. If your application depends on a DB and that is offline, when you get the exception about it you can only display an error message
  • Exceptions can be unexpected, and can reveal design or implementation flaws. For example, an implementation flaw can be the situation in which you have a redundant DB but when you fail to connect to frist mirror you don't try with the second

For the third point, it's important to log exceptions and periodically analyse logs to find any weird situation. So, let's begin with the concrete answer.

First of all

think about "handling" the exception. When you write every single code line, think about the possible problems that may prevent it from completing, and think about the possible corrective actions. if any are possible. An error message is not a good handling way, it's the latest strategy.

Don't start to write try-catch(Exception), but prefer specific exceptions. If you need to parse strings to numbers etc, then expect FormatException, if you need to cast from Object to your type expect InvalidCastException

When you write lower-level layers

don't hesitate to throw exceptions!! Don't do like many folks do, ie. return null or use (like ANSI C) a boolean return value and reference parameters. Exceptions are there for that. If you can handle an exception (ie. you don't find a local file but you know you have a remote backup, so handle FileNotFoundException by calling the remote mirror, but if you can't still connect then ultimately throw) then do it and try to resume computation, but if you cannot then throw. And don't forget to throw the inner exception, if present, because it is helpful for logging in the highest layer.

Basically, you can still decide to throw an exception on your own even if you don't catch any! And this is highly recommended especially when function parameters are invalid!

Another good option is to still log in the underlying layers. You actually want to log no matter an exception occurs.

When you log

remember to give an adequate severity to the messages. If you find via code that your DB is offline, that's not an unexpected exception. Still log it as an error, but don't worry about code bugs when you investigate the logs. Instead, if you catch an exception that your code is unable to recognize (a NullReferenceException is a classic example) then log with highest severity, ie. fatal, to give it maximum priority!

A good strategy for ASP.NET

can surely be based upon Page.OnError method. If you have a base page class for all of the pages of your site, you should definitely override that method. In that method, you should first log your exception.

You also shouldn't abuse of try-catch(Exception) blocks, because if you don't catch an exception you can't handle with catch, you will have to handle it via OnError.

When you run such a method, don't immediately think about Server.RemoveError(). You can prefer to have a static HTML page for HTTP 500 error (that is triggered when an unhandled exception bubbles to ASP.NET runtime) that displays a courtesy message to the user.

Briefly

  1. Don't hesitate to throw in underlying layers if anything strange occurs
  2. As said by your advice, don't handle exceptions you are unable to handle (if you catch an exception you can't handle, rethrow it)
  3. LOG!!!!!!!!!!!!!!!!!
  4. Don't disclose exception details to final users on a public website, never!! By default, ASP.NET prevents that from occurring, but you could still use OnError to print stack trace
  5. Use OnError, or Application_Error as single central point to handle all unexpected exceptions
  6. Periodically examine logs against error/fatal messages to find issues with your code, then think about maintaining/debugging/fixing it

Is there a way in C# to catch all exceptions from a Control/Form?

I'm not sure it's a good idea to put all the error handling code in a single place.

Error handling should better take place next to the operation it handles.

The whole point of error handling is to change the program behaviour where the program encounters an error. This means you have to write specific code at that location, and that you can't put everything in only one place as you seem to want to.

However, maybe what you need is only an helper method to log stuff, etc.


Unhandled exceptions handlers (Application.ThreadException, AppDomain.CurrentDomain.UnhandledException) do exists, but that's not what they are for.

You should use those to handle unexpected exceptions, ie, something wrong occurred that you didn't think of, and you want to handle this case nicely (For example, you may want to log the error, or display a nice error box to the user, or gently close the program)

If you know an Exception may occur somewhere, that "somewhere" is the good place to write your exception handling code.

C# (not ASP/MVC/WinForms) - Catch all exceptions in a class

I would take a look at using something like Castle Dynamic Proxy.

This will allow your class method calls to be intercepted in a generic way, which would give you a central place to put a "catch-all" exception handler. (That said, it's unclear to me how your classes are actually instantiated, which might make this approach problematic)



Related Topics



Leave a reply



Submit