Error Handling¶
Error Handling, MediatR’da exception’ları yönetmek için kullanılan bir mekanizmadır. Global exception handling ve özel exception tipleri kullanılır.
Error Handling Özellikleri¶
- Global Exception Handling: Tüm exception’lar merkezi olarak yönetilir
- Custom Exception Types: Özel exception tipleri tanımlanır
- Error Response: Hata durumunda özel response’lar dönülür
- Logging: Hatalar loglanır
Exception Tipleri¶
Custom Exceptions¶
public class ValidationException : Exception
{
public ValidationException(string message) : base(message)
{
}
public ValidationException(string message, Exception innerException)
: base(message, innerException)
{
}
}
public class NotFoundException : Exception
{
public NotFoundException(string message) : base(message)
{
}
}
public class UnauthorizedException : Exception
{
public UnauthorizedException(string message) : base(message)
{
}
}
Exception Middleware¶
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 InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred");
await HandleExceptionAsync(context, ex);
}
}
private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
var response = new ErrorResponse();
switch (exception)
{
case ValidationException validationException:
context.Response.StatusCode = StatusCodes.Status400BadRequest;
response = new ErrorResponse
{
StatusCode = StatusCodes.Status400BadRequest,
Message = validationException.Message
};
break;
case NotFoundException notFoundException:
context.Response.StatusCode = StatusCodes.Status404NotFound;
response = new ErrorResponse
{
StatusCode = StatusCodes.Status404NotFound,
Message = notFoundException.Message
};
break;
case UnauthorizedException unauthorizedException:
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
response = new ErrorResponse
{
StatusCode = StatusCodes.Status401Unauthorized,
Message = unauthorizedException.Message
};
break;
default:
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
response = new ErrorResponse
{
StatusCode = StatusCodes.Status500InternalServerError,
Message = "Internal server error"
};
break;
}
await context.Response.WriteAsJsonAsync(response);
}
}
public class ErrorResponse
{
public int StatusCode { get; set; }
public string Message { get; set; }
}
Error Handling Best Practices¶
-
Exception Types - Her hata tipi için özel exception sınıfı - Exception mesajları açıklayıcı olmalı - Inner exception’lar korunmalı
-
Error Response - HTTP status code’ları doğru kullanılmalı - Error response’ları standart olmalı - Hata detayları uygun seviyede olmalı
-
Logging - Tüm hatalar loglanmalı - Log seviyeleri doğru kullanılmalı - Sensitive data loglanmamalı
-
Testing - Exception senaryoları test edilmeli - Error response’ları test edilmeli - Logging test edilmeli
Error Handling Pipeline¶
Error handling pipeline üzerinden geçer:
- Exception Catching
- Exception Logging
- Error Response Generation
- Response Sending
public class ErrorHandlingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly ILogger<ErrorHandlingBehavior<TRequest, TResponse>> _logger;
public ErrorHandlingBehavior(ILogger<ErrorHandlingBehavior<TRequest, TResponse>> logger)
{
_logger = logger;
}
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken)
{
try
{
return await next();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error handling request {RequestName}", typeof(TRequest).Name);
throw;
}
}
}
Error Handling Registration¶
services.AddMediatR(cfg => {
cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
cfg.AddBehavior(typeof(ErrorHandlingBehavior<,>));
});
app.UseMiddleware<ExceptionMiddleware>();