.NET Core中如何自定义ProblemDetails对象?
自定义ProblemDetail对象并返回的实现方案
1. 定义自定义ProblemDetail类
先创建包含你所需字段的自定义错误对象,可根据业务需求添加额外属性:
public class CustomProblemDetail { public string Title { get; set; } public int Status { get; set; } public string Detail { get; set; } public string Instance { get; set; } // 自定义扩展字段 public string ErrorCode { get; set; } public DateTime Timestamp { get; set; } = DateTime.UtcNow; }
2. 编写API错误捕获中间件
这个中间件可以同时捕获请求处理中的异常,以及4xx级别的API状态码错误,返回自定义对象:
public class ApiErrorHandlingMiddleware { private readonly RequestDelegate _next; private readonly ILogger<ApiErrorHandlingMiddleware> _logger; public ApiErrorHandlingMiddleware(RequestDelegate next, ILogger<ApiErrorHandlingMiddleware> logger) { _next = next; _logger = logger; } public async Task InvokeAsync(HttpContext context) { try { await _next(context); // 处理4xx级别的API错误(未触发异常的状态码错误) if (!context.Response.HasStarted && context.Response.StatusCode >= 400 && context.Response.StatusCode < 500) { await HandleStatusCodeErrorAsync(context); } } catch (Exception ex) { _logger.LogError(ex, "API请求出现未处理异常"); await HandleExceptionErrorAsync(context, ex); } } private async Task HandleStatusCodeErrorAsync(HttpContext context) { context.Response.ContentType = "application/json"; var problemDetail = new CustomProblemDetail { Status = context.Response.StatusCode, Title = GetStatusTitle(context.Response.StatusCode), Detail = "请求处理失败", Instance = context.Request.Path, ErrorCode = $"HTTP_{context.Response.StatusCode}" }; await context.Response.WriteAsJsonAsync(problemDetail); } private async Task HandleExceptionErrorAsync(HttpContext context, Exception ex) { context.Response.ContentType = "application/json"; context.Response.StatusCode = StatusCodes.Status500InternalServerError; // 可根据异常类型定制错误信息 var problemDetail = new CustomProblemDetail { Status = StatusCodes.Status500InternalServerError, Title = "服务器内部错误", Detail = ex.Message, Instance = context.Request.Path, ErrorCode = "INTERNAL_SERVER_ERROR" }; await context.Response.WriteAsJsonAsync(problemDetail); } private string GetStatusTitle(int statusCode) { return statusCode switch { StatusCodes.Status400BadRequest => "无效请求", StatusCodes.Status401Unauthorized => "未授权访问", StatusCodes.Status403Forbidden => "禁止访问", StatusCodes.Status404NotFound => "请求资源不存在", _ => "请求错误" }; } }
3. 注册中间件
在Program.cs中注册这个中间件,注意要放在路由中间件之前、其他业务中间件之后:
var builder = WebApplication.CreateBuilder(args); // 注册服务... var app = builder.Build(); // 注册自定义API错误处理中间件 app.UseMiddleware<ApiErrorHandlingMiddleware>(); // 其他中间件配置 app.UseRouting(); app.UseAuthorization(); app.MapControllers(); app.Run();
4. 可选:基于默认ProblemDetails扩展(若不想完全自定义对象)
如果只是需要在默认ProblemDetails基础上添加字段,可以替换内置的ProblemDetailsFactory:
public class CustomProblemDetailsFactory : ProblemDetailsFactory { private readonly ApiBehaviorOptions _options; public CustomProblemDetailsFactory(IOptions<ApiBehaviorOptions> options) { _options = options.Value; } public override ProblemDetails CreateProblemDetails(HttpContext httpContext, int? statusCode = null, string title = null, string type = null, string detail = null, string instance = null) { var problemDetails = base.CreateProblemDetails(httpContext, statusCode, title, type, detail, instance); // 添加自定义扩展字段 problemDetails.Extensions.Add("ErrorCode", $"HTTP_{statusCode}"); problemDetails.Extensions.Add("Timestamp", DateTime.UtcNow); return problemDetails; } public override ValidationProblemDetails CreateValidationProblemDetails(HttpContext httpContext, ModelStateDictionary modelStateDictionary, int? statusCode = null, string title = null, string type = null, string detail = null, string instance = null) { var validationProblemDetails = base.CreateValidationProblemDetails(httpContext, modelStateDictionary, statusCode, title, type, detail, instance); validationProblemDetails.Extensions.Add("ErrorCode", "VALIDATION_ERROR"); validationProblemDetails.Extensions.Add("Timestamp", DateTime.UtcNow); return validationProblemDetails; } }
然后在服务注册时替换:
builder.Services.AddControllers(); builder.Services.AddTransient<ProblemDetailsFactory, CustomProblemDetailsFactory>();
内容的提问来源于stack exchange,提问作者Master
相关产品推荐
相关产品推荐

