Yes. Some.
The correct configuration would initially look like this:
<configuration>
...
<system.web>
...
<customErrors mode="On">
<error statusCode="404" redirect="~/Views/Erro/404.html" />
</customErrors>
...
</system.web>
...
</configuration>
But I particularly do not like it because it goes against the MVC architecture. I'm more the Actions approach of Controllers to produce more interesting error screens:
<configuration>
...
<system.web>
...
<customErrors mode="On" defaultRedirect="~/Error/Index">
<error statusCode="404" redirect="~/Error/NotFound"/>
<error statusCode="403" redirect="~/Error/BadRequest"/>
</customErrors>
...
</system.web>
...
</configuration>
The problem is that this mode causes the transfer to return a code 302, and soon after a code 200, which hurts the HTTP protocol, since we had an error (ie codes 400 onwards), then we need adapt again.
<configuration>
...
<system.web>
...
<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/Error/Index">
<error statusCode="404" redirect="~/Error/NotFound"/>
<error statusCode="403" redirect="~/Error/BadRequest"/>
</customErrors>
...
</system.web>
...
</configuration>
Another problem: this does not work right because ASP.NET MVC uses Server.Transfer
to redirect to static content, not dynamic. In the end, the configuration would look like this:
<configuration>
...
<system.web>
...
<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/Views/Erro/404.html">
<error statusCode="404" redirect="~/Error/NotFound"/>
<error statusCode="403" redirect="~/Error/BadRequest"/>
</customErrors>
...
</system.web>
...
</configuration>
Anyway, I do not really like either way. I'd prefer one, proposed by this answer here :
Global.asax.cs
public class MvcApplication : HttpApplication
{
protected void Application_EndRequest()
{
if (Context.Response.StatusCode == 404)
{
Response.Clear();
var rd = new RouteData();
rd.Values["controller"] = "Errors";
rd.Values["action"] = "NotFound";
IController c = new ErrorsController();
c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
}
}
}
ErrorsController.cs
public sealed class ErrorsController : Controller
{
public ActionResult NotFound()
{
ActionResult result;
object model = Request.Url.PathAndQuery;
if (!Request.IsAjaxRequest())
result = View(model);
else
result = PartialView("_NotFound", model);
return result;
}
}
I'd say that's the most decent way to handle HTTP errors in an MVC application.
Incidentally, it pays to read the answer I put here. It explains more fully all the problems of using HTTP errors by configuration.