You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 00:22:26