我正在编写一个中间件,以便在收到来自我的域的业务通知消息时将状态代码更改为 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
}
]
}
有任何建议来修复此问题或其他解决方案以获取这些通知吗?
来自文档
警告
接下来不要打电话。将响应发送到客户端后调用。 响应开始后对 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);