【问题标题】:ASP.NET Core 2.2 - ProblemDetailsASP.NET Core 2.2 - 问题详情
【发布时间】:2019-07-17 23:21:31
【问题描述】:

我最近将支持 Swagger 的 ASP.NET Core 项目升级到了 2.2。我注意到我的所有错误响应现在都显示为 ProblemDetails 响应正文。

{
  "type": "string",
  "title": "string",
  "status": 0,
  "detail": "string",
  "instance": "string",
  "additionalProp1": {},
  "additionalProp2": {},
  "additionalProp3": {}
}

根据Microsoft,这是意料之中的——我对此很满意。

但是,由于某种原因,我的项目不会为某些默认返回码(例如 401)返回这些。这是(我相信是)我的启动配置的相关部分。

    services
        .AddAuthentication(options => {
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(jwtOptions => {
            jwtOptions.Authority = jwtConfiguration.Authority;
            jwtOptions.TokenValidationParameters.ValidAudiences = jwtConfiguration.Audiences;
        });

    // Add framework services.
    services
        .AddMvcCore(options => {
            options.Filters.Add<OperationCancelledExceptionFilterAttribute>();
        })
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
        .AddAuthorization()
        .AddApiExplorer()
        .AddJsonFormatters()
        .AddCors()
        .AddJsonOptions(options => options.SerializerSettings.Converters.Add(new StringEnumConverter()));

    services.AddVersionedApiExplorer(
        options => {
            //The format of the version added to the route URL  
            options.GroupNameFormat = "'v'VVV";
            //Tells swagger to replace the version in the controller route  
            options.SubstituteApiVersionInUrl = true;
        });

    services.AddApiVersioning(option => {
        option.ReportApiVersions = true;
    });

    // Add data protection
    services.AddDataProtection();

    //Add swagger
    services.AddSwaggerGen(c => {
        c.SwaggerDoc("v1", new Info { Version = "1.0", ...});
        c.SwaggerDoc("v2", new Info { Version = "2.0", ...});
        c.AddSecurityDefinition("Bearer", ...});
        c.AddSecurityRequirement(...);
        c.DescribeAllEnumsAsStrings();
        c.EnableAnnotations();
    });

    //Add documentation for end point
    services.AddSwaggerGen(...});

使用此设置,任何未经授权的请求都会以 401 告终,但不会附加任何问题详细信息。这不是我所理解的应该发生的事情,我无法弄清楚我需要按下哪个开关来实现它。

【问题讨论】:

    标签: c# asp.net-core-2.2


    【解决方案1】:

    默认情况下,仅在模型验证失败时返回 400 个 BadRequests 问题详细信息。这是通过将 ApiController 属性添加到控制器时自动插入的过滤器来完成的。这种行为可能会受到ApiBehaviorOptions 的影响,在过滤器的情况下,特别是InvalidModelStateResponseFactory

    发生的其他异常也不会映射到问题详细信息,因为您必须编写自己的中间件。类似于以下内容:

    public class ExceptionMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IActionResultExecutor<ObjectResult> _executor;
    
        public ExceptionMiddleware(RequestDelegate next, IActionResultExecutor<ObjectResult> executor)
        {
            _next = next;
            _executor = executor;
        }
    
        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _next(context);
            } 
            catch(Exception ex) 
            {
                await ExecuteProblemDetailsResultAsync(context, ex);
            }
        }
    
        private Task ExecuteProblemDetailsResultAsync(HttpContext context, Exception ex)
        {
            var routeData = context.GetRouteData();
            var actionContext = new ActionContext(context, routeData, new ActionDescriptor());
    
            var problemDetails = ex.ToProblemDetails();
            return _executor.ExecuteAsync(actionContext, new ObjectResult(problemDetails));
        }
    }
    

    但这仍然不会返回 401 Unauthorized 作为问题详细信息,因为您应该在中间件中捕获 HttpResponse 并将其转换为问题详细信息。

    但是因为我遇到了同样的问题,并且希望我的 API 中的所有异常都作为问题详细信息返回,所以我创建了一个名为 HttpExceptions 的 NuGet 包,它可以为你解决这个问题 :) 看看,也许它是对你来说也是一个很好的解决方案。

    【讨论】:

    • 我发现这个包非常方便:nuget.org/packages/Hellang.Middleware.ProblemDetails
    • 我也尝试使用一个库 - Hellang.Middleware.ProblemDetails。至少对于需要装饰对旧 WCF 服务的调用的简单新 API 项目来说看起来不错。需要更多的练习,然后它会起作用。但这是使用标准消息作为结果的一个很好的理由 (RFC7807)。
    猜你喜欢
    • 2019-10-30
    • 2020-04-22
    • 2019-06-19
    • 1970-01-01
    • 2019-09-28
    • 2019-06-28
    • 2019-07-28
    • 2019-07-21
    • 1970-01-01
    相关资源
    最近更新 更多