0

Let's imagine we have a service CustomerService:

public class CustomerService
{
    public Customer GetCustomer(string customerName)
    {
        if(string.IsNullOrWhiteSpace(customerName))
            throw new ArgumentNullException(nameof(customerName));

        try
        {
            var customer = customerRepository.GetByName(customerName);
            return customer;
        }
        catch(Exception ex)
        {
            _logger.Error(ex);
            throw;
        }
    }
}

This service is used in a controller MyController:

public class MyController : Controller
{
     /* Properties */

     public ActionResult CustomerStuff(string customerName)
     {
          try
          {
              var customer = _customerService.GetCustomer(customerName);
              return View(customer);
          }
          catch (Exception ex)
          {
              // Redirect to error page, etc...
          }
     }
}

The problem with this is that I hide possible ArgumentNullException which is probably caused by a bug in my code. I never expect anything to pass null to GetCustomer, but catch(Exception) in MyController hides this exception with the rest of exceptions. On the other hand, on production I want to redirect users if something goes wrong in the CustomerService, because e.g. connection timeout occured.

How can this problem be resolved without tons of code, such as:

try
{

}
catch (Exception ex) when (!(ex is ArgumentNullException))
{
    // handle timeouts, network availability, etc..
}

One possible solution I can see is creating a custom exception, such as ServiceException and throwing it inside try/catch in GetCustomer method. Is there any other technique that is maybe more common?

  • 1
    Can you create a "developer mode," where the error page shows the full exception details that caused the page to be shown? When releasing into production, the "developer mode" feature would be disabled to avoid bothering the end-users with such details. – Bart van Ingen Schenau Jun 18 '18 at 9:31
  • @BartvanIngenSchenau I think this is the way to go. Thank you, I will try it and let you know. – FCin Jun 18 '18 at 10:27
  • @BartvanIngenSchenau jup asp.net core supports this: docs.microsoft.com/en-us/aspnet/core/fundamentals/… – keuleJ Jun 12 at 16:30
1

Just change your service to:

public class CustomerService
{
    public Customer GetCustomer(string customerName)
    {
        try
        {
            if(string.IsNullOrWhiteSpace(customerName))
                throw new ArgumentNullException(nameof(customerName));

            var customer = customerRepository.GetByName(customerName);
            return customer;
        }
        catch(Exception ex)
        {
            _logger.Error(ex);
            throw;
        }
    }
}

That way, your logger catches the argument error, along with all other errors. The controller then needs no special logic to handle specific exceptions.

  • The point is I don't want to catch ArgumentNullException. This exception is probably caused by a bug in the code and I don't want to hide it in catch. I want it to crash application. – FCin Jun 18 '18 at 10:06
  • @FCin, You aren't catching it as your catch block contains a throw. So it gets logged but still then gets sent to the controller for it to "crash your app", ie show a 500 internal error page. – David Arno Jun 18 '18 at 10:13
  • So your solution involves removing try/catch in MyController and handling exceptions by configuring error pages? – FCin Jun 18 '18 at 10:19
  • 1
    @FCin, so you literally want them to crash the app, rather than showing an error page? Seems extreme, but you can handle this for example by calling Thread.Abort(ex) in the logger if it's one of those exceptions. That method throws a ThreadAbortException. which can be caught, but is automatically re-thrown at the end of the catch block. It cannot therefore be stopped from propagating all the way up through your app.This will therefore log the error in the live system as well as killing the app dead. – David Arno Jun 18 '18 at 10:34
  • 1
    @FCin, "I want to crash app, because this will happen only for developers". No, that is effectively impossible. Unless you never release your app, at some stage you'll have to ship it and it will contain bugs, not matter how many weeks, months, years etc you've spent testing. So end users will experience this. – David Arno Jun 18 '18 at 10:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.