I make a post request to the api and my middleware seems to be working but when it gets to return OK the program crashes and gives this error Status Code cannot be set because the response has already started
Program.cs
app.UseMiddleware<MyExceptionHandlerMiddleware>();
app.UseMiddleware<MyShortCircuitMiddleware>();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
bool recreateDatabase = builder.Configuration.GetValue("recreateDatabase", false);
using var scope = app.Services.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<MyDatabaseContext>();
if (recreateDatabase)
{
await dbContext.Database.EnsureDeletedAsync();
await dbContext.Database.MigrateAsync();
}
await dbContext.Database.MigrateAsync();
DomainValidator.GetInstance().Initialize(builder.Configuration);
app.Run();
MyExceptionHandlerMiddleware.cs
public async Task InvokeAsync(HttpContext httpContext)
{
try
{
await _next(httpContext);
}
catch (Exception ex)
{
_logger.LogCritical("[Exp][API] Something went wrong: {}", ex);
await HandleExceptionAsync(httpContext, ex);
}
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var json = JsonSerializer.Serialize(new {
title = "Something went wrong!",
status = (int)HttpStatusCode.InternalServerError,
errorCode =(int)ErrorCode.ServerFault
});
await context.Response.WriteAsync(json);
}
CodePudding user response:
This error message indicates that, you are trying to set the status code after the response body is written.
to resolve this, try setting the status code before anything is written.
In your case in the HandleExceptionAsync method try setting the status code on start of the function.
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ContentType = "application/json";
var json = JsonSerializer.Serialize(new {
title = "Something went wrong!",
status = (int)HttpStatusCode.InternalServerError,
errorCode = (int)ErrorCode.ServerFault
});
await context.Response.WriteAsync(json);
}
CodePudding user response:
I make a post request to the api and my middleware seems to be working but when it gets to return OK the program crashes and gives this error Status Code cannot be set because the response has already started.
Well, the exception you are getting it pretty obvious and its not because of your app.UseMiddleware<MyExceptionHandlerMiddleware>();
middleware but for the later one which is app.UseMiddleware<MyShortCircuitMiddleware>();
. As you might know, while you have written await _next(httpContext);
within your current middleware it won't execute anymore and control would pass to your next request delegate which is app.UseMiddleware<MyShortCircuitMiddleware>();
And if you have written any response there soon you would encounter the exception because we cannot write response twice within a single httpcontext this causing your error in your scenario as you can see below:
Issue Reproduced:
Note: Once you have written to the Response/stream the other middleware wont be able to write again within the same context. You have to replace the Response/stream if you want to write and pass one down the pipeline. I would highly recommend you to
In addition, please be aware of following invokation:
You can get more details here in official document