您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# .NET 6开发TodoList应用中如何实现全局异常处理
## 前言
在软件开发过程中,异常处理是保证应用程序健壮性和可靠性的重要组成部分。特别是在Web API开发中,良好的异常处理机制能够:
1. 防止敏感信息泄露
2. 提供一致的错误响应格式
3. 便于问题排查和日志记录
4. 提升客户端开发体验
本文将详细介绍在.NET 6 TodoList应用开发中实现全局异常处理的完整方案,涵盖从基础配置到高级场景的全套解决方案。
## 一、理解中间件和异常处理管道
### 1.1 .NET Core中间件机制
在ASP.NET Core中,请求处理管道是由一系列中间件组成的:
```csharp
public void Configure(IApplicationBuilder app)
{
app.UseMiddleware1();
app.UseMiddleware2();
// ...
}
处理位置 | 优点 | 局限性 |
---|---|---|
Controller Action | 针对性强 | 重复代码多 |
中间件 | 全局统一 | 无法访问具体上下文 |
过滤器 | 面向切面 | 执行顺序复杂 |
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)
{
await HandleExceptionAsync(context, ex);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
// 处理逻辑...
}
}
// Program.cs
app.UseMiddleware<ExceptionHandlingMiddleware>();
public class ErrorResponse
{
public int StatusCode { get; set; }
public string Message { get; set; }
public string Details { get; set; }
public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
var response = new ErrorResponse();
switch (exception)
{
case ValidationException vex:
response.StatusCode = StatusCodes.Status400BadRequest;
response.Message = "Validation error";
response.Details = vex.Errors;
break;
case NotFoundException nex:
response.StatusCode = StatusCodes.Status404NotFound;
response.Message = nex.Message;
break;
default:
response.StatusCode = StatusCodes.Status500InternalServerError;
response.Message = "Internal server error";
response.Details = _env.IsDevelopment() ? exception.ToString() : null;
break;
}
await context.Response.WriteAsJsonAsync(response);
}
.NET 6内置了对RFC 7807 ProblemDetails的支持:
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
var problemDetails = new ProblemDetails
{
Title = "An error occurred",
Status = StatusCodes.Status500InternalServerError,
Detail = exception.Message
};
await context.Response.WriteAsJsonAsync(problemDetails);
}
// 在Program.cs中配置
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var problemDetails = new ValidationProblemDetails(context.ModelState)
{
Title = "Validation error",
Status = StatusCodes.Status400BadRequest
};
return new BadRequestObjectResult(problemDetails);
};
});
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
_logger.LogError(exception, "Unhandled exception occurred: {Message}", exception.Message);
// ...其余处理逻辑
}
// Program.cs
builder.Services.AddApplicationInsightsTelemetry();
// 在中间件中
_telemetryClient.TrackException(exception);
[Fact]
public async Task Should_Return404_WhenItemNotFound()
{
// Arrange
var middleware = new ExceptionHandlingMiddleware(
next: (innerHttpContext) => throw new NotFoundException("Item not found"),
logger: Mock.Of<ILogger<ExceptionHandlingMiddleware>>());
var context = new DefaultHttpContext();
// Act
await middleware.InvokeAsync(context);
// Assert
Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode);
}
[Fact]
public async Task Get_NonExistingItem_ReturnsNotFound()
{
// Arrange
var client = _factory.CreateClient();
// Act
var response = await client.GetAsync("/api/todoitems/999");
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
var content = await response.Content.ReadFromJsonAsync<ErrorResponse>();
Assert.NotNull(content);
Assert.Equal("Item not found", content.Message);
}
以下是TodoList应用的完整异常处理中间件实现:
public class ExceptionHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionHandlingMiddleware> _logger;
private readonly IHostEnvironment _env;
public ExceptionHandlingMiddleware(
RequestDelegate next,
ILogger<ExceptionHandlingMiddleware> logger,
IHostEnvironment env)
{
_next = next;
_logger = logger;
_env = env;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An unhandled exception has occurred");
await HandleExceptionAsync(context, ex);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/problem+json";
var problemDetails = new ProblemDetails
{
Instance = context.Request.Path,
Extensions = { ["traceId"] = context.TraceIdentifier }
};
switch (exception)
{
case ValidationException vex:
problemDetails.Title = "Validation error";
problemDetails.Status = StatusCodes.Status400BadRequest;
problemDetails.Extensions["errors"] = vex.Errors;
break;
case NotFoundException nex:
problemDetails.Title = "Not found";
problemDetails.Status = StatusCodes.Status404NotFound;
problemDetails.Detail = nex.Message;
break;
case UnauthorizedAccessException _:
problemDetails.Title = "Unauthorized";
problemDetails.Status = StatusCodes.Status401Unauthorized;
break;
default:
problemDetails.Title = "Internal server error";
problemDetails.Status = StatusCodes.Status500InternalServerError;
problemDetails.Detail = _env.IsDevelopment() ? exception.ToString() : null;
break;
}
context.Response.StatusCode = problemDetails.Status.Value;
await context.Response.WriteAsJsonAsync(problemDetails);
}
}
在本文中,我们全面探讨了在.NET 6 TodoList应用中实现全局异常处理的完整方案:
良好的异常处理策略能够显著提升API的可靠性和可维护性,是专业级应用开发不可或缺的部分。
”`
这篇文章总计约5400字,涵盖了从基础到高级的全局异常处理实现方案,包含了代码示例、表格对比、最佳实践等丰富内容,采用标准的Markdown格式,可以直接用于技术博客发布或文档编写。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。