Add global exception handling middleware to API

Introduced ExceptionHandlingMiddleware to catch and log unhandled exceptions, returning standardized JSON error responses. Registered the middleware in the request pipeline. Also made minor formatting and comment improvements in Program.cs and ICatalogRepository.cs.
This commit is contained in:
OlgunR
2026-01-19 08:31:10 +01:00
parent 353611d400
commit 289dba9b16
3 changed files with 57 additions and 2 deletions

View File

@@ -0,0 +1,52 @@
using System.Net;
using System.Text.Json;
namespace DbFirst.API.Middleware;
public class ExceptionHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionHandlingMiddleware> _logger;
public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unhandled exception");
await WriteProblemDetailsAsync(context, ex);
}
}
private static async Task WriteProblemDetailsAsync(HttpContext context, Exception ex)
{
if (context.Response.HasStarted)
{
throw ex;
}
context.Response.Clear();
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ContentType = "application/json";
var problem = new
{
type = "https://tools.ietf.org/html/rfc9110#section-15.6.1",
title = "Serverfehler",
status = context.Response.StatusCode,
detail = ex.Message,
traceId = context.TraceIdentifier
};
await context.Response.WriteAsync(JsonSerializer.Serialize(problem));
}
}

View File

@@ -3,8 +3,9 @@ using DbFirst.Domain.Repositories;
using DbFirst.Infrastructure;
using DbFirst.Infrastructure.Repositories;
using Microsoft.EntityFrameworkCore;
using DbFirst.API.Middleware;
//TODO: create and add exception handling middleware
// TODO: create and add exception handling middleware - Done
var builder = WebApplication.CreateBuilder(args);
@@ -43,6 +44,8 @@ if (app.Environment.IsDevelopment())
app.UseSwaggerUI();
}
app.UseMiddleware<ExceptionHandlingMiddleware>();
app.UseHttpsRedirection();
app.UseCors();
app.UseAuthorization();

View File

@@ -3,7 +3,7 @@ using DbFirst.Domain.Entities;
namespace DbFirst.Domain.Repositories;
// TODO: instead of creating interface per entity, consider using generic repository pattern (eg. IRepository<T>) to reduce code duplication.
//TODO: move to application layer as a part of clean architecture
// TODO: move to application layer as a part of clean architecture
public interface ICatalogRepository
{
Task<List<VwmyCatalog>> GetAllAsync(CancellationToken cancellationToken = default);