第十章 异常处理和日志记录

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;
        }
    }
}

wechat_2025-07-31_105805_938


posted @ 2025-08-07 09:11  高宏顺  阅读(230)  评论(0)    收藏  举报