ASP.NET Core 上的 HttpStatus 代码不正确

Incorrect HttpStatus code on ASP.NET Core

我在 ASP.NET 核心应用程序上有一个异常中间件:

try
{
    await _next(httpContext);
}
catch (MyException exception)
{
    httpContext.Response.ContentType = "application/json";
    httpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;

    await httpContext.Response.WriteAsync(exception.Message);
}

在这个例子中,我们发送 "Forbidden"(403 http 状态代码)但 我总是收到 500。我在 Swagger 和 Google Chrome 上检查了这个,但我不明白原因。

您可能在管道中的错误位置注册了中间件。您在 startup.cs 中放置中间件的顺序会有所不同。例如:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.Use(async (context, next) =>
    {
        try
        {
            await next();
        }
        catch (Exception ex)
        {
            context.Response.StatusCode = StatusCodes.Status403Forbidden;

            await context.Response.WriteAsync(ex.Message);
        }
    });

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseMvc();
}

在上面的代码中,我在管道的开头注册了类似于您的中间件。 ASP.NET Core 将按照您放置的顺序处理任何请求,因此我的自定义中间件将 运行 首先处理请求。但是,响应是自下而上处理的。因此,在示例中,当控制器(或任何地方)抛出异常时,UseDeveloperExceptionPageUseExceptionHandler 将首先接收任何异常,处理它并将状态代码更改为 500。

如果我们将顺序更改为:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.Use(async (context, next) =>
    {
        try
        {
            await next();
        }
        catch (Exception ex)
        {
            context.Response.StatusCode = StatusCodes.Status403Forbidden;

            await context.Response.WriteAsync(ex.Message);
        }
    });

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseMvc();
}

现在我们已经将我们的处理程序注册到请求的内置异常处理程序之后,但更重要的是,在它们之前进行响应。因此,在这种情况下,当控制器抛出异常时,我们的处理程序将捕获它、处理它并将状态代码更改为我们想要的。其他异常处理程序将看不到异常(除非另一个中间件处理程序在我们之后抛出异常)。