.NET 6 Web API:提前捕获异常并替换为其他异常
在ASP.NET Core 6中拦截类库异常并转换为API自定义异常
完全可以实现这个需求,下面提供两种实用方案:
方案一:全局异常转换中间件
通过自定义中间件捕获管道中抛出的类库异常,将其转换为API项目的自定义异常后重新抛出,控制器Action的try-catch就能捕获到转换后的异常。
实现步骤
- 编写异常转换中间件:
public class ExceptionTranslationMiddleware { private readonly RequestDelegate _next; public ExceptionTranslationMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { try { await _next(context); } catch (LibrarySpecificExceptionA ex) { // 转换为API自定义异常,保留原始异常作为InnerException throw new ApiExceptionA("执行操作A时出错", ex); } catch (LibrarySpecificExceptionB ex) { throw new ApiExceptionB("执行操作B时出错", ex); } // 其他未匹配异常可继续向上抛出或按需处理 } }
- 在Program.cs中注册中间件(需放在路由与端点中间件之间):
var builder = WebApplication.CreateBuilder(args); // 省略其他服务注册逻辑 var app = builder.Build(); // 省略其他中间件配置 app.UseRouting(); // 注册异常转换中间件 app.UseMiddleware<ExceptionTranslationMiddleware>(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); app.Run();
方案二:服务包装层统一处理
如果需要精细化控制(仅针对特定类库服务调用做转换),可在API项目中编写包装类,封装对类库服务的调用,在包装类内完成异常转换。
实现步骤
- 编写类库服务的包装类:
public class LibraryServiceWrapper { private readonly ILibraryService _libraryService; public LibraryServiceWrapper(ILibraryService libraryService) { _libraryService = libraryService; } public async Task<OperationResult> ExecuteOperationA() { try { return await _libraryService.ExecuteOperationA(); } catch (LibrarySpecificExceptionA ex) { throw new ApiExceptionA("操作A执行失败,请检查参数", ex); } } public async Task<AnotherResult> ExecuteOperationB() { try { return await _libraryService.ExecuteOperationB(); } catch (LibrarySpecificExceptionB ex) { throw new ApiExceptionB("操作B执行失败,资源不可用", ex); } } }
- 在Program.cs中注册包装类:
builder.Services.AddScoped<LibraryServiceWrapper>(); // 注册类库服务(若未注册) builder.Services.AddScoped<ILibraryService, LibraryServiceImpl>();
- 在控制器中注入包装类并调用:
[ApiController] [Route("api/operations")] public class OperationsController : ControllerBase { private readonly LibraryServiceWrapper _serviceWrapper; public OperationsController(LibraryServiceWrapper serviceWrapper) { _serviceWrapper = serviceWrapper; } [HttpGet("operation-a")] public async Task<IActionResult> GetOperationA() { try { var result = await _serviceWrapper.ExecuteOperationA(); return Ok(result); } catch (ApiExceptionA ex) { // 处理转换后的API异常 return BadRequest(ex.Message); } } }
注意事项
- 转换异常时务必保留原始异常作为
InnerException,便于排查问题根源。 - 中间件方案适合全局统一处理,包装层方案适合特定服务的精细化控制,可根据项目需求选择。
内容的提问来源于stack exchange,提问作者user1171946
相关产品推荐
相关产品推荐

