I am testing custom error handling using similar URLs http://localhost:52200/<
and http://localhost:52200/<xyz
. Somehow, I am getting inconsistent results.
Web.Config:
<!--MVC pipeline-->
<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/Error.aspx">
<error statusCode="404" redirect="~/404.aspx" />
<error statusCode="500" redirect="~/500.aspx" />
</customErrors>
<!--IIS pipeline-->
<httpErrors errorMode="Custom">
<remove statusCode="404"/>
<error statusCode="404" path="404.html" responseMode="File"/>
<remove statusCode="500"/>
<error statusCode="500" path="500.html" responseMode="File"/>
</httpErrors>
When customErrors mode="Off"
, both return identical HTTP 400 Bad Request
:
However, when customErrors mode="On"
, only http://localhost:52200/<
returns HTTP 400 Bad Request
and then redirects to Error.aspx
.
Now, http://localhost:52200/<xyz
returns HTTP 500 Internal Server Error
and goes to:
When I remove ResponseRewrite, both return HTTP 302 Found
and redirect to Error.aspx
. I do not want this because I lose the http error code.
What am I doing wrong?
Solved! For a reason unknown to me, MVC pipeline requires defaultRedirect
to point toward a .html
file:
<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/Error.html">
Adding Response.ContentType = "text/html";
in Global.asax.cs
avoids a known issue where the error page would render as text:
protected void Application_Error()
{
var exception = Server.GetLastError();
if (exception is HttpException httpException)
{
Response.ContentType = "text/html";
Response.StatusCode = httpException != null ? httpException.GetHttpCode() : (int)HttpStatusCode.InternalServerError;
}
}
Also, Response.StatusCode
ensures that the correct HTTP error code reaches the client (e.g. 400, 503, etc.) instead of a 200.
With these 2 blocks in web.config
and global.asax.cs
and no change to IIS, both http://localhost:52200/<
and http://localhost:52200/<a
now return HTTP 400 Bad Request
and display Error.html
as expected.