I am attempting to "catch all" 500 and 404 errors within my MVC application and I can't seem to grasp what is needed, even after reading all the articles and questions out there.
Web.config
(this allows 500 errors to go to ~/Views/Shared/Error.cshtml
):
<system.web>
<customErrors mode="On" redirectMode="ResponseRewrite" />
</system.web>
I've setup the HomeController
to throw an error to test the above setup:
public ActionResult Index()
{
//Testing errors
throw new Exception("Exception");
return View();
}
In my Global.asax.cs
, I have the following to log the 500 errors:
protected void Application_Error()
{
var ex = Server.GetLastError();
//Custom ExceptionLog
new ExceptionLogHelper().Add("Application_Error", Response.Status, ex);
}
Now for the 404 errors:
In my RouteConfig.cs
, I have the following routes, but can't seem to catch all 404s:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Error",
url: "Error/{code}",
defaults: new { controller = "Error", action = "Index", code = UrlParameter.Optional }
);
//routes.MapRoute(
// name: "Controllers",
// url: "{controller}/{action}/{id}",
// defaults: new { controller = "Error", action = "Index", code = UrlParameter.Optional }
//);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
//Keep at bottom
routes.MapRoute("CatchAll", "{*url}", new { controller = "Error", action = "Index", name = "no-route-found", code = "404" });
}
}
CatchAll
at the bottom is doing a good job catching everything that does not match the preceeding routes.
I have a bunch more test scenarios, but one that is bugging me is the following UrlParameter:
http://localhost:64275/does/not/exist/
The above URL is essentially http://localhost:64275/{controller}/{action}/{id}
I don't have a Controller named does
, and I thought that defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
would default to the Home
controller with Action of Index
if no Controller was matched.
Another example that works:
http://localhost:64275/a/a/a/a/ (because it has 4 parts, not 3 or less)
Can someone explain where I might be going wrong? ...and what I am not understanding?
Should I be implementing something like this: .Net MVC Routing Catchall not working (Darin Dimitrov's answer)
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
HttpException httpException = exception as HttpException;
if (httpException != null)
{
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Error");
routeData.Values.Add("action", "HttpError500");
if (httpException.GetHttpCode() == 404)
{
routeData.Values["action"] = "HttpError404";
}
Server.ClearError();
Response.Clear();
IController errorController = new ErrorController();
errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}
}