DEV Community

Victor
Victor

Posted on

ASP.NET Core - Fundamentals - Error Handling

There are some ways to handle exceptions while we working with ASP.NET Core

1. Use try-catch block

Best practice when using "throw"

  • Throw ex: loose stack trace on downstream layer
    For example, an exception has occurred in the Data layer, Business layer catch this exception and use 'Throw Ex', at API layer will lose stack trace

  • Throw: keep stack trace on downstream layer
    For example, an exception has occurred in the Data layer, Business layer catch this exception and use 'Throw', at API layer will get a stack trace in detail

  • Throw new Exception/ or Custom Exception: it will make downstream layer losing stack trace in detail
    Only use at a lower level, the downstream level should use "Throw", we will keep stack trace on the downstream level

2. Use custom middleware to centralize exception handling

    /// <summary>
    /// Step 1: Create a middleware class
    /// </summary>
    public class CustomExceptionHandlerMiddleware
    {
        private readonly RequestDelegate _next;
        ILogger<CustomExceptionHandlerMiddleware> _logger;
        public CustomExceptionHandlerMiddleware(RequestDelegate next
            , ILogger<CustomExceptionHandlerMiddleware> logger)
        {
            _next = next;
            _logger = logger;
        }
        public async Task InvokeAsync(HttpContext context)
        {
            try
            {
                await _next(context);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error while processing your request");
                await HandleExceptionAsync(context, ex);
            }
        }

        private Task HandleExceptionAsync(HttpContext context, Exception exception)
        {
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            return context.Response.WriteAsync(exception.Message);
        }
    }

    /// <summary>
    /// Step 2: Create a extension method to use our middleware
    /// </summary>

    public static class CustomExceptionHandlerMiddlewareExtensions
    {
        public static IApplicationBuilder UseCustomExceptionHandlers(this IApplicationBuilder app)
        {
            return app.UseMiddleware<CustomExceptionHandlerMiddleware>();
        }
    }
Enter fullscreen mode Exit fullscreen mode

3. Centralize exception handling with IExceptionFilter

Implement an ExceptionFilter class

Implement ExceptionFilter class

Add to the configuration method (Sample for ASP.NET Core 3.0)

Configure Custom Exception filter

Throw an exception when needed.

Exception throwing

4. [From ASP.NET Core 8] - Use IExceptionHandler

This interface has TryHandleAsync method.
If Exception can handle => return true;
If Not => return false

Implement of IExceptionHandler

public class GlobalExceptionHandler : IExceptionHandler
    {
        private readonly ILogger<GlobalExceptionHandler> logger;

        public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
        {
            this.logger = logger;
        }

        public async ValueTask<bool> TryHandleAsync(
            HttpContext httpContext,
            Exception exception,
            CancellationToken cancellationToken)
        {
            this.logger.LogError(exception, "Exception occurred: {Message}", exception.Message);

            var problemDetails = new ProblemDetails
            {
                Status = StatusCodes.Status500InternalServerError,
                Title = "Server error -- apply IExceptionHandler for Global"
            };

            httpContext.Response.StatusCode = problemDetails.Status.Value;

            await httpContext.Response
                .WriteAsJsonAsync(problemDetails, cancellationToken);

            return true;
        }
    }
Enter fullscreen mode Exit fullscreen mode

Use the handler in Program file

// User Exception Handler
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
builder.Services.AddProblemDetails();

var app = builder.Build();

app.UseExceptionHandler();
Enter fullscreen mode Exit fullscreen mode

Top comments (0)