WebAPI global exception handler There is a global exception handler in our WebAPI application that looks like the following:

public class ApiExceptionHandler : IExceptionHandler
{
    public async Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
    {

        var exceptionType = context.Exception.GetType();

        if (exceptionType == typeof(ResourceNotFoundException))
        {
            context.Result = new ResponseMessageResult(
                context.Request.CreateResponse(HttpStatusCode.NotFound, context.Exception.Message));
        }

        else if (exceptionType == typeof(UserNotFoundException))
        {
            context.Result = new ResponseMessageResult(
                context.Request.CreateResponse(HttpStatusCode.Unauthorized, context.Exception.Message));
        }

        else if (exceptionType == typeof(UserAlreadyExistsExeption))
        {
            context.Result = new ResponseMessageResult(
                context.Request.CreateResponse(HttpStatusCode.Conflict, context.Exception.Message));
        }

        ...

        else
        {
            context.Result = new ResponseMessageResult(
                context.Request.CreateResponse(HttpStatusCode.InternalServerError, "An unexpected error occured"));
        }
    }
}


And each exception has the following form:

public class UserAlreadyExistsExeption: Exception
{
    public UserAlreadyExistsExeption()
    {
    }

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

    public UserAlreadyExistsExeption(string message, Exception inner) : base(message, inner)
    {

    }
}


And can be thrown in the code like the following:

//If user exists
throw new UserAlreadyExistsExeption("User already exists");


I was thinking of making all our custom exceptions implement a IHasHttpErrorCode so each one has its own HttpErrorCode - usage like the following:

Interface: 

public interface IHasHttpErrorCode
{
    HttpStatusCode GetHttpStatusCode();
}


Exception:

public class UserAlreadyExistsExeption: Exception, IHasHttpErrorCode
{
    public UserAlreadyExistsExeption()
    {
    }

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

    public UserAlreadyExistsExeption(string message, Exception inner) : base(message, inner)
    {

    }

    public HttpStatusCode GetHttpStatusCode() {
        return HttpStatusCode.Conflict;
    }
}


Global Error Handler:

public class ApiExceptionHandler : IExceptionHandler
{
    public async Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
    {

        var exceptionType = context.Exception as IHasHttpErrorCode;


        if (customException != null) { 
            context.Result = new ResponseMessageResult(
                context.Request.CreateResponse(customException.GetHttpStatusCode(), context.Exception.Message));
        } 
        else
        {
            context.Result = new ResponseMessageResult(
                context.Request.CreateResponse(HttpStatusCode.InternalServerError, "An unexpected error occured"));
        }
    }
}


Is this a valid approach to improve the existing code? Is there anything else I should look to improve?
Using the interface is definitely an improvement, but what I lack in your code is common base exception, something like ServerException that could be used to distinguish other exceptions (e.g. IndexOutOfRangeException or whatever) from your exceptions (useful for catching).

That common base could be made abstract to force you to define HttpStatusCode

public abstract class ServerException: Exception {
//  standard constructors...
    public abstract HttpStatusCode GetHttpStatusCode();
}


Now, if you derive any custom exception from this (as you should, maybe creating some other abstract derived exceptions for some groups of problems), then you have to override (define) the code (or it would have to remain abstract and you won't be able to throw it).

public class UserAlreadyExistsExeption: ServerException {
//  again standard .ctors
    override public HttpStatusCode GetHttpStatusCode() =&gt; HttpStatusCode.Conflict;
}


Alternative would be to use public get-only property and initialize it in the constructor, maybe even having one exception type (and use try-catch-when), but I am not sure that can be used in your code (would require perfect 1-to-1 match between exception types and status codes).

Make message default

public class UserAlreadyExistsExeption: Exception, IHasHttpErrorCode
{
    public UserAlreadyExistsExeption(): base("User already exists") {}
}


and

throw new UserAlreadyExistsExeption();


instead of

throw new UserAlreadyExistsExeption("User already exists");


Maybe even handling localization in the default constructor, if needed.