Matthias
Matthias

Reputation: 13414

ASP.NET C# Catch all exceptions in a class

I know this is not the way to do it, and it isn't clean at all. I just wonder if it's possible.

If I have a class with a bunch of methods

public class Foo {

   methodA() {}

   methodB() {}

   methodC() {}

}

Is it possible to catch all exceptions that could possibly occur without having to write a try/catch in each method?

Upvotes: 18

Views: 11213

Answers (5)

sra
sra

Reputation: 23973

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
    });
}

Upvotes: 24

Michail Smith
Michail Smith

Reputation: 67

You could write a higher order function to handle the exceptions, which would make it somewhat cleaner.

private T FooExceptionHandler(Func<T> function)
{
   try
   {
      return function();
   }
   catch
   {
      //handle it
   }
}

You can replace Func with Action if you don't have a return value. You can use it in two ways, outside of the function:

FooExceptionHandler(MethodA);

or inside each function:

MethodA()
{
   return FooExceptionHandler(()=>
      {
         //Function body goes here
      });
}

Upvotes: 5

usr-local-ΕΨΗΕΛΩΝ
usr-local-ΕΨΗΕΛΩΝ

Reputation: 26874

By default, in ASP.NET you can override the OnError method and then do Server.ClearError to dispose of the exception.

I'm not sure if it applies to your case (only works in Page and Global.asax)

Upvotes: 0

Dev.Jaap
Dev.Jaap

Reputation: 151

You can handle it in the function that calls these methods...

Upvotes: 0

Femaref
Femaref

Reputation: 61437

No, there isn't. try/catch blocks can only occur in methods. You could use some sort of AOP framework however to automatically generate those blocks. postcrap is a pretty lightweight AOP component.

Upvotes: 0

Related Questions