'Headers are read-only, response has already started
I am trying to catch and format the exception thrown by the resource filter but getting this error. The middleware is working for exceptions thrown from controller level but getting this - "System.InvalidOperationException: Headers are read-only, response has already started" error while trying to write to the response in case of resource level errors.
Code of my Resource Filter:
public class TestingAsyncResourceFilter : IAsyncResourceFilter
{
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
{
Console.WriteLine("Resource filter executing");
var resourceExecutedContext = await next();
Console.WriteLine("Resource filter executed");
if (!resourceExecutedContext.ModelState.IsValid)
{
throw new CustomUPException();
}
}
}
Code of middleware:
public class ResponseFormatterMiddleware : IMiddleware
{
private readonly ILogger<ResponseFormatterMiddleware> _logger;
public ResponseFormatterMiddleware(ILogger<ResponseFormatterMiddleware> logger)
{
_logger = logger;
}
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
try
{
Console.WriteLine("Before execution");
await next(context);
Console.WriteLine("After Execution");
}
catch(CustomUPException e)
{
Console.WriteLine("Here we are");
await context.Response.WriteAsJsonAsync(
new ResponseDto()
{
statusCode = e.statusCode,
message = e.message
}); // getting error
}
catch(Exception e)
{
_logger.LogError(e.Message);
context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
await context.Response.WriteAsJsonAsync(
new ResponseDto()
{
success = false,
message = "Request failed"
});
}
}
}
Code of my controller:
[Route("api/[controller]")]
[ApiController]
public class TestingController : ControllerBase
{
[HttpPost("/resource")]
public async Task<UserDto> testingResource( [FromBody] UserDto dto)
{
if (dto.email.Contains("hell"))
{
throw new CustomUPException(); //working
}
return dto;
}
}
Solution 1:[1]
Instead of using resource filter, I have used this strategy for formatting model validation errors as the documentation suggests.
Curious to know more about the raised issue though. Thanks in advance
// Add services to the container.
builder.Services.AddControllers().ConfigureApiBehaviorOptions(
options =>
{
options.InvalidModelStateResponseFactory = context =>
{
if (!context.ModelState.IsValid)
{
var data = new Dictionary<string, string?>();
//My Response formatter
var modelStateDictionary = context.ModelState;
foreach (var key in modelStateDictionary.Keys)
{
var errors = modelStateDictionary[key]?.Errors;
data.TryAdd(key, errors?[0].ErrorMessage);
}
return new ObjectResult(new UniversalResponseDto()
{
data = data,
statusCode = (int)HttpStatusCode.UnprocessableEntity,
sucess = false,
message = "One or more validation error occured"
})
{
StatusCode = (int)HttpStatusCode.UnprocessableEntity,
};
}
return new ObjectResult(context.HttpContext.Response);
};
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
