.NET 7 Web API全局统一BaseResponse格式响应实现问询
.NET 7 REST API 全场景统一响应格式实现方案
先明确统一响应模型的基础定义(示例):
public class ResponseBase<T> { public bool Success { get; set; } public T? Data { get; set; } public string? Message { get; set; } public int StatusCode { get; set; } public static ResponseBase<T> SuccessResult(T data, int statusCode = 200) { return new ResponseBase<T> { Success = true, Data = data, StatusCode = statusCode }; } public static ResponseBase<T> FailResult(string message, int statusCode) { return new ResponseBase<T> { Success = false, Message = message, StatusCode = statusCode }; } } // 无数据场景的简化版本 public class ResponseBase : ResponseBase<object> { public static new ResponseBase FailResult(string message, int statusCode) { return new ResponseBase { Success = false, Message = message, StatusCode = statusCode }; } }
一、自定义全局响应中间件
覆盖路由不存在、未授权、服务器异常等全局场景,捕获并包装成统一格式:
public class GlobalResponseMiddleware { private readonly RequestDelegate _next; private readonly ILogger<GlobalResponseMiddleware> _logger; public GlobalResponseMiddleware(RequestDelegate next, ILogger<GlobalResponseMiddleware> logger) { _next = next; _logger = logger; } public async Task InvokeAsync(HttpContext context) { try { await _next(context); // 处理非200状态码的响应 if (context.Response.StatusCode != StatusCodes.Status200OK) { await HandleStatusCodeResponse(context); } } catch (Exception ex) { _logger.LogError(ex, "未处理的服务器异常"); await HandleExceptionResponse(context, ex); } } private async Task HandleStatusCodeResponse(HttpContext context) { context.Response.ContentType = "application/json"; var response = context.Response; ResponseBase result; switch (response.StatusCode) { case StatusCodes.Status401Unauthorized: result = ResponseBase.FailResult("未授权访问", StatusCodes.Status401Unauthorized); break; case StatusCodes.Status403Forbidden: result = ResponseBase.FailResult("无权限访问", StatusCodes.Status403Forbidden); break; case StatusCodes.Status404NotFound: result = ResponseBase.FailResult("请求资源不存在", StatusCodes.Status404NotFound); break; case StatusCodes.Status400BadRequest: result = ResponseBase.FailResult("请求参数错误", StatusCodes.Status400BadRequest); break; default: result = ResponseBase.FailResult($"服务器错误,状态码:{response.StatusCode}", response.StatusCode); break; } await context.Response.WriteAsJsonAsync(result); } private async Task HandleExceptionResponse(HttpContext context, Exception ex) { context.Response.ContentType = "application/json"; context.Response.StatusCode = StatusCodes.Status500InternalServerError; var result = ResponseBase.FailResult("服务器内部异常", StatusCodes.Status500InternalServerError); // 开发环境可显示异常详情,生产环境关闭 if (context.RequestServices.GetRequiredService<IWebHostEnvironment>().IsDevelopment()) { result.Message += $":{ex.Message}"; } await context.Response.WriteAsJsonAsync(result); } }
在Program.cs中注册中间件(注意顺序:放在UseRouting之后,UseAuthorization之前):
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); var app = builder.Build(); // 注册全局响应中间件 app.UseMiddleware<GlobalResponseMiddleware>(); app.UseRouting(); app.UseAuthorization(); app.MapControllers(); app.Run();
二、动作过滤器覆盖控制器内置结果
处理控制器直接返回的NotFound()、Unauthorized()等内置结果,强制包装成统一格式:
public class ResponseWrapFilter : IAsyncActionFilter { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var resultContext = await next(); // 已为统一格式则跳过 if (resultContext.Result is ObjectResult objResult && objResult.Value is ResponseBase) { return; } ResponseBase response; switch (resultContext.Result) { case NotFoundResult: response = ResponseBase.FailResult("请求资源不存在", StatusCodes.Status404NotFound); break; case UnauthorizedResult: response = ResponseBase.FailResult("未授权访问", StatusCodes.Status401Unauthorized); break; case ForbidResult: response = ResponseBase.FailResult("无权限访问", StatusCodes.Status403Forbidden); break; case BadRequestResult: response = ResponseBase.FailResult("请求参数错误", StatusCodes.Status400BadRequest); break; case ObjectResult objectResult: // 正常响应包装为成功结果 response = ResponseBase.SuccessResult(objectResult.Value, objectResult.StatusCode ?? StatusCodes.Status200OK); break; default: response = ResponseBase.SuccessResult(null, StatusCodes.Status200OK); break; } resultContext.Result = new ObjectResult(response) { StatusCode = response.StatusCode }; } }
在Program.cs中注册全局过滤器:
builder.Services.AddControllers(options => { options.Filters.Add<ResponseWrapFilter>(); });
三、验证覆盖场景
- 控制器返回
NotFound():过滤器直接包装为统一格式 - 路由不存在:中间件捕获404状态码返回统一格式
- 未授权/无权限:中间件捕获401/403状态码返回统一格式
- 服务器异常:中间件捕获异常返回统一格式
- 正常业务响应:过滤器自动包装为成功结果
内容的提问来源于stack exchange,提问作者Aleks Vujic
相关产品推荐
相关产品推荐

