无法更改自定义中间件.net 7 最小 API 中的状态代码

问题描述 投票:0回答:1

我正在编写一个中间件,以便在收到来自我的域的业务通知消息时将状态代码更改为 BadRequest,但收到消息“无法设置 StatusCode,因为响应已开始”。

在 catch 块中一切都很好,至少它可以工作。

这是我的代码:

public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        var response = context.Response;
        var statusCode = (int)HttpStatusCode.InternalServerError;
        response.ContentType = "application/json";

        try
        {
            await next(context);

            if (_notificationContext.HasNotifications)
            {
                response.StatusCode = (int)HttpStatusCode.BadRequest;

                var resultNotifications = new Result<Notification>() { Errors = new List<Notification>() };
                resultNotifications.Errors.AddRange(_notificationContext.Notifications);

                await response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(resultNotifications));
                return;
            }
        }
        catch (Exception exception)
        {
            var correlationId = response.Headers["X-Correlation-ID"].FirstOrDefault() ?? string.Empty;
            Result<Notification> resultNotifications = null;
            if (_notificationContext.HasNotifications)
            {
                statusCode = (int)HttpStatusCode.BadRequest;
                resultNotifications = new Result<Notification>() { Errors = new List<Notification>() };
                resultNotifications.Errors.AddRange(_notificationContext.Notifications);
                using (LogContext.PushProperty("Notifications", resultNotifications.Errors, true))
                {
                    Log.Error(exception, "There are validation notifications to be analyzed.");
                }
            }
            else
            {
                Log.Error(exception, "An error occurred with the request. See the log for more details.");
            }

            if (!response.HasStarted)
            {
                response.StatusCode = statusCode;
                await context.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(resultNotifications ?? GetErrorMessage(correlationId)));
            }
        }

    }

我希望得到这个结果,状态代码为 400:

{
    "Data": null,
    "Errors": [
        {
            "Key": "Token",
            "Message": "Token de autenticação de autenticação do MarketPlace Liberty",
            "Alerta": false
        }
    ]
}

但我收到的状态代码为 200:

{
    "requestId": "62BD6460AC644A37A68F912FCAC8DA7F",
}{
    "Data": null,
    "Errors": [
        {
            "Key": "Token",
            "Message": "Token de autenticação de autenticação do MarketPlace Liberty",
            "Alerta": false
        }
    ]
}

有任何建议来修复此问题或其他解决方案以获取这些通知吗?

middleware .net-7.0 minimal-apis
1个回答
0
投票

来自文档

警告

接下来不要打电话。将响应发送到客户端后调用。 响应开始后对 HttpResponse 的更改会引发 例外。例如,设置标头和状态代码会引发 例外。调用 next 后写入响应正文:

可能导致违反协议。例如,写得比 规定内容长度。可能会损坏正文格式。例如, 将 HTML 页脚写入 CSS 文件。 HasStarted 是一个有用的提示 指示标头是否已发送或正文是否已写入。

使用您的示例,我将通过删除中间件并使用过滤器来重构它:

app.MapGet("/weatherforecast", () =>
{
    var forecast =  Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
}).AddEndpointFilter(async (efiContext, next) =>
    {
       
        var result = await next(efiContext);
        //add check if has notifications here
        return Results.BadRequest(new { key = "Key", message = "Validation message" }); 
        
    })
.WithName("GetWeatherForecast")
.WithOpenApi();

从上面的代码片段中,我丢弃了对象

result
并创建了一个要与
BadRequest
响应一起返回的新对象,最好是为了使这个更干净,您应该在开始任何响应之前找到一种方法来评估此检查
if (_notificationContext.HasNotifications)
,这样在您的过滤器或中间件中:

if (_notificationContext.HasNotifications)
    //return bad request
else
    await next(context);
© www.soinside.com 2019 - 2024. All rights reserved.