第十章 异常处理和日志记录
10.1 全局异常处理
异常处理中间件
public class GlobalExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<GlobalExceptionMiddleware> _logger;
public GlobalExceptionMiddleware(RequestDelegate next, ILogger<GlobalExceptionMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An unexpected error occurred");
await HandleExceptionAsync(context, ex);
}
}
private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
var response = context.Response;
var errorResponse = new ErrorResponse();
switch (exception)
{
case NotFoundException:
response.StatusCode = 404;
errorResponse.Message = exception.Message;
break;
case ValidationException:
response.StatusCode = 400;
errorResponse.Message = exception.Message;
break;
case UnauthorizedAccessException:
response.StatusCode = 401;
errorResponse.Message = "Unauthorized";
break;
default:
response.StatusCode = 500;
errorResponse.Message = "An unexpected error occurred";
break;
}
var jsonResponse = JsonSerializer.Serialize(errorResponse);
await context.Response.WriteAsync(jsonResponse);
}
}
public class ErrorResponse
{
public string Message { get; set; }
public string Detail { get; set; }
}
10.2 日志记录
配置Serilog
// 安装包
// dotnet add package Serilog.AspNetCore
// dotnet add package Serilog.Sinks.Console
// dotnet add package Serilog.Sinks.File
// 在Program.cs中配置
using Serilog;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.File("logs/log-.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
try
{
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();
// 其他配置...
var app = builder.Build();
app.UseSerilogRequestLogging();
// 其他中间件...
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}
在控制器中使用日志
[ApiController]
[Route("api/[controller]")]
public class TodoItemsController : ControllerBase
{
private readonly ITodoRepository _repository;
private readonly ILogger<TodoItemsController> _logger;
public TodoItemsController(ITodoRepository repository, ILogger<TodoItemsController> logger)
{
_repository = repository;
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
{
_logger.LogInformation("Getting all todo items");
try
{
var items = await _repository.GetAllAsync();
_logger.LogInformation("Successfully retrieved {Count} todo items", items.Count());
return Ok(items);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting todo items");
throw;
}
}
[HttpPost]
public async Task<ActionResult<TodoItem>> CreateTodoItem(TodoItem item)
{
_logger.LogInformation("Creating new todo item: {Name}", item.Name);
try
{
var createdItem = await _repository.AddAsync(item);
_logger.LogInformation("Successfully created todo item with ID: {Id}", createdItem.Id);
return CreatedAtAction(nameof(GetTodoItem),
new { id = createdItem.Id }, createdItem);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while creating todo item: {Name}", item.Name);
throw;
}
}
}


浙公网安备 33010602011771号