I\'ve been fighting to get custom error pages to work and keep finding my way back to simply using a static page. Though the static page works, it would require remaking the
I got around the same issue in my ASP.Net MVC projects by piping everything through .Net via handlers.
First an ErrorController
was created to handle request errors and not found requests like.
[AllowAnonymous]
public class ErrorController : Controller {
// GET: Error
public ActionResult NotFound() {
Response.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
Response.TrySkipIisCustomErrors = true;
HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
HttpContext.Response.TrySkipIisCustomErrors = true;
return View();
}
public ActionResult Error() {
Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
Response.TrySkipIisCustomErrors = true;
return View();
}
}
You will notice that I call TrySkipIisCustomErrors
to try to avoid IIS errors
Then a base controller to handle all unknown actions that would map to the ErrorController.NotFound
action was created.
public abstract class FrontOfficeControllerBase : Controller {
protected override void HandleUnknownAction(string actionName) {
var data = ViewData;
//Custom code to resolve the view.
//ViewResult view = this.View(c => c.NotFound());
//Manually create view with view Data
ViewResult view = new ViewResult();
view.ViewData = new ViewDataDictionary();
view.ViewData["controller"] = "Error";
view.ViewData["action"] = "NotFound";
if (data != null && data.Count > 0) {
data.ToList().ForEach(view.ViewData.Add);
}
Response.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
Response.TrySkipIisCustomErrors = true;
view.ExecuteResult(this.ControllerContext);
}
}
All Controllers
would inherit from this base controller.
A catch all route was configured after all other routes.
routes.MapRoute(
name: "404-NotFound",
url: "NotFound",
defaults: new { controller = "Error", action = "NotFound" }
);
routes.MapRoute(
name: "500-Error",
url: "Error",
defaults: new { controller = "Error", action = "Error" }
);
routes.MapRoute(
name: "CatchAll",
url: "{*any}",
defaults: new { controller = "Error", action = "NotFound" });
This made sure that if a route was not matched to any of my controllers it would safely route to the ErrorController.NotFound
action.
For the views, I created the respective NotFound.shtml
and Error.cshtml
paged in the Views/Shared
folder and they benefited from access to the root layout, which is what I think you were looking for.
In the end I was able to remove both the customErrors
and httpErrors
from web.config
as there was no longer any need for them as every request was managed by the handlers and routed accordingly.
The original idea for this structure came from this article where I mixed and matched the available options till I found a solution that worked/suited my needs.
Exception handling in ASP.NET MVC (6 methods explained)
Hope this helps.