Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid using try ... catch in controllers?

I try to handle my exceptions in the lower layers of my application since they can be handled (logging them). However, there are errors which should crash the application like if a parameter is NULL and shouldnt in that case i would throw a ArgumentNullException.

If you take into consideration the controller layer which call out the service layer. I want to avoid the service layer to throw exceptions because i want to handle all of them here (logging) but i fell like this is impossible in such case (like the NULL case).

So what is the best way to avoid using try...catch in controllers ? or should i really use try...catch in a controller ?

like image 862
Rushino Avatar asked Dec 16 '22 05:12

Rushino


2 Answers

I prefer to handle all unhandled exceptions (things that are not supposed to happen) in the Application_Error method. It is where you could log the exception and based on its nature show the proper error view.

Things like custom model binders, validators, action filters, ... also could allow for intercepting some exceptional conditions to avoid polluting your controllers with try/catch everywhere.

For everything that I intend to handle, like business errors, etc... there's nothing wrong with using try/catch, or even better use if statements and have the service layer notify you whether some operation succeeded or failed (TryXXX pattern.)

So as always, the answer to your question is: it depends. It depends on how your application is organized, how is your service layer organized, what potential errors could happen, what are the errors that you would like to explicitly handle, ... many, many, many factors and of course many, many, many possible solutions.

like image 193
Darin Dimitrov Avatar answered Dec 31 '22 01:12

Darin Dimitrov


To collaborate on Darin Dimitrov's answer

Things like custom model binders, validators, action filters, ... also could allow for intercepting some exceptional conditions to avoid polluting your controllers with try/catch everywhere.

This is what I prefer. You can make a IExceptionFilter which would look like this:

public class ExceptionLoggingFilter : IExceptionFilter
{
    private ILogger _logger;

    public ExceptionLoggingFilter(ILogger logger)
    {
        _logger = logger;
    }

    public void OnException(ExceptionContext context)
    {
        Exception ex = context.Exception;

        if (_logger != null)
        {
            _logger.log(ex)
        }
    }
    context.ExceptionHandled = true; //see note
}

note: if you do not want to rethrow the exception you can add that. If you only want to log, but have another filter for handing it, you can remove that line.

then in your Global.aspx you'd do:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new ExceptionLoggingFilter(new Log4NetLogger()));
}

I prefer creating filters to creating a Application_Error, because for me it makes it easier to separate different functionalities. (such as logging, checking if the application can handle it, etc)

like image 30
Ron Sijm Avatar answered Dec 31 '22 01:12

Ron Sijm