It may be easiest to implement an IAsyncExceptionFilter
in your application - this can pick up unhandled exceptions on controller actions and rewrite them into a form you'd like, such as the 422 HTTP response desired here. If implementing an IAsyncExceptionFilter
you can use the below code which was tested with ASP.NET Core 3.1 to return the exception message to the client as plain text:
public override async Task OnExceptionAsync(ExceptionContext context) {
if (!context.HttpContext.Response.HasStarted) {
var errorMessage = "Could not do that because of X reason."; // or you could use `context.Exception.Message` if it is secure in your application to do so
var responseBytes = Encoding.UTF8.GetBytes(errorMessage).AsMemory();
context.Result = new UnprocessableEntityResult();
context.HttpContext.Response.StatusCode = 422;
context.HttpContext.Response.ContentType = "text/plain;charset=UTF-8";
context.HttpContext.Response.ContentLength = responseBytes.Length;
await context.HttpContext.Response.BodyWriter.WriteAsync(responseBytes);
context.ExceptionHandled = true;
} else {
// if the response has already started, this can't be used. You will have to figure
// out a different solution.
}
}
If not using an IAsyncExceptionFilter
, you can still use most of the above code, it would be a matter of setting the same properties on the Response.HttpContext
object available in your controller's handler, and then returning the UnprocessableEntityResult
.
Note that setting both the ContentType
and ContentLength
headers correctly will prevent net::ERR_INCOMPLETE_CHUNKED_ENCODING
errors with some browsers. In this case, the ContentLength
will be accurate because we get the bytes of the error string from Encoding.UTF8
first and set the ContentLength
to the length of those bytes, not just the string length. Also, the ContentType
header includes the charset=UTF-8
qualifier to remove any ambiguity.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…