Exception Handling In ASP.NET Core Web API

Introduction

Exception handling in ASP.NET Core Web API is essential to provide a reliable and robust application. Handling exceptions properly helps in debugging, logging, and providing meaningful error responses to clients. Here are some common approaches for exception handling in ASP.NET Core Web API:

Global Exception Handling Middleware

Use the built-in exception handling middleware to catch unhandled exceptions globally. In the Startup.cs file, in the Configure method, add the following:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    // Other middleware and configurations
}

In production, the UseExceptionHandler middleware will redirect to the specified error page or endpoint. In development, the UseDeveloperExceptionPage middleware will provide detailed error information.

Custom Exception Middleware

Create a custom middleware to handle exceptions globally and log them. This middleware should be added early in the pipeline.

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<ExceptionMiddleware> _logger;

    public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            _logger.LogError($"Unexpected error: {ex}");
            context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            await context.Response.WriteAsync("An unexpected error occurred.");
        }
    }
}

Register this middleware in the Configure method of Startup.cs:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseMiddleware<ExceptionMiddleware>();

    // Other middleware and configurations
}

Action Filter for Specific Exceptions

Use action filters to handle exceptions for specific actions or controllers. Create a custom action filter attribute:

public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        var exception = context.Exception;

        // Log or handle the exception as needed

        context.Result = new ObjectResult(new { message = "An error occurred." })
        {
            StatusCode = (int)HttpStatusCode.InternalServerError
        };
    }
}

Apply this filter to controllers or actions

[ApiController]
[Route("api/[controller]")]
[CustomExceptionFilter]
public class ValuesController : ControllerBase
{
    // Controller actions
}

Use ProblemDetails for API Responses

ASP.NET Core provides the ProblemDetails class for standardized error responses. Return ProblemDetails from your actions to provide consistent error details to clients.

[ApiController]
[Route("api/[controller]")]
public class ValuesController : ControllerBase
{
    [HttpGet("{id}")]
    public IActionResult Get(int id)
    {
        if (id < 0)
        {
            var problemDetails = new ProblemDetails
            {
                Status = (int)HttpStatusCode.BadRequest,
                Title = "Invalid input",
                Detail = "Id must be greater than or equal to 0"
            };

            return BadRequest(problemDetails);
        }

        // Process the request

        return Ok($"Value with id {id}");
    }
}

Conclusion

Choose the approach that best fits your application's needs, and consider combining multiple strategies for comprehensive exception handling.