Throwing custom exceptions from injected service to controller

Viewed 559

This should be a very simple question, but I can't seem to find an answer.

I'm using a standard dependency injection to inject a custom service into a controller in NET Core Web API.

private readonly IMyService _myService;
public MyController(IMyService MyService)
{
    _myService= MyService;
}

IMyService contains all the methods with logic and MyService implements it. Now, is it possible to expose custom exception types to the controller via interface, so I'd be able throw those exceptions from MyService and catch them in MyController? As far as I understand C# - interfaces can't have custom classes as properties. Or is this approach wrong entirely? How else should I correctly communicate errors of different kinds from service back to controller?

1 Answers

Yes, you can!

Example:

Suppose you have this custom exception

using System;
using System.Runtime.Serialization;

namespace SO.DI._001.Exceptions
{
    public class SomeCustomException : Exception
    {
        public SomeCustomException()
        {
        }

        public SomeCustomException(string message) : base(message)
        {
        }

        public SomeCustomException(string message, Exception innerException) : base(message, innerException)
        {
        }

        protected SomeCustomException(SerializationInfo info, StreamingContext context) : base(info, context)
        {
        }
    }
}

Suppose your service is

using SO.DI._001.Exceptions;

namespace SO.DI._001.Services
{
    public class MyService : IMyService
    {
        public void DoSomething()
        {
            throw new SomeCustomException();
        }
    }
}

So, Your controller can be like this:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using SO.DI._001.Exceptions;
using SO.DI._001.Services;
using System;

namespace SO.DI._001.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private readonly ILogger<WeatherForecastController> _logger;
        private readonly IMyService _myService;

        public WeatherForecastController(ILogger<WeatherForecastController> logger,
                                         IMyService myService)
        {
            _logger = logger;
            _myService = myService;
        }

        [HttpGet]
        public IActionResult Get()
        {
            try
            {
                _myService.DoSomething();
            }
            catch (SomeCustomException ex)
            {
                _logger.LogError($"{nameof(SomeCustomException)} {ex.Message}");

                //Handle it
            }
            catch (AnotherCustomerException ex) when (ex.Message == "blabla")
            {
                _logger.LogError($"{nameof(AnotherCustomerException)} {ex.Message} blablabla");

                //Handle it
            }
            catch (AnotherCustomerException ex)
            {
                _logger.LogError($"{nameof(AnotherCustomerException)} {ex.Message}");

                //Handle it
                //Handle it
            }
            catch (Exception ex)
            {
                //This is the default exception
            }


            return Ok();
        }
    }
}
Related