53

Is it possible to create a final route that catches all .. and bounces the user to a 404 view in ASP.NET MVC?

NOTE: I don't want to set this up in my IIS settings.

1

8 Answers 8

81

Found the answer myself.

Richard Dingwall has an excellent post going through various strategies. I particularly like the FilterAttribute solution. I'm not a fan of throwing exceptions around willy nilly, so i'll see if i can improve on that :)

For the global.asax, just add this code as your last route to register:

routes.MapRoute( "404-PageNotFound", "{*url}", new { controller = "StaticContent", action = "PageNotFound" } ); 
Sign up to request clarification or add additional context in comments.

8 Comments

I've tried this, but it doesn't work. I have put the route under my default route, but i still get 404 errors.
Can you please explain what exactly I have to assuming I am very new to MVC.
2 things. a) add that last route to your route list. b) create a controller (in my example, i called it StaticContentController) with an Action method (in my example, i added a method called PageNotFound(..)) add logic this method to display the 404 page not found, View.
If you still have the default route (I.E. {controller}/{action}/{id}) in RegisterRoutes() it will trap all URLs that match the format of a normal MVC request. In other words the catch-all route can only intercept a bad URL if it doesn't fit the normal format (blah/blah/blah/blah). In the case of a non-existent controller the exception must be handled through conventional ASP.NET handling. Theres a good description of handling at stackoverflow.com/questions/619895/…
@RonnBlack is right. I overcome this by just explicitly create a route for each controller. BUT the magic {*url} still not overcome this issue. What if the mapped URL into route is available but the controller/action itself did not found. If I browse to /Home/About123 ugly asp.net error page still come out because the route not reach to the {*url} but handled in my home route.
|
20

This question came first, but the easier answer came in a later question:

Routing for custom ASP.NET MVC 404 Error page

I got my error handling to work by creating an ErrorController that returns the views in this article. I also had to add the "Catch All" to the route in global.asax.

I cannot see how it will get to any of these error pages if it is not in the Web.config..? My Web.config had to specify:

customErrors mode="On" defaultRedirect="~/Error/Unknown" 

and then I also added:

error statusCode="404" redirect="~/Error/NotFound" 

Hope this helps.

I love this way now because it is so simple:

 <customErrors mode="On" defaultRedirect="~/Error/" redirectMode="ResponseRedirect"> <error statusCode="404" redirect="~/Error/PageNotFound/" /> </customErrors> 

3 Comments

That's what I have now, but I'm trying to replace it with a better solution which will not first send a 302 response to the client but a 404 directly. Change the redirectMode to ResponseRewrite and you'll find it does not work any more... :-(
@LouisSomers Since this answer, I have found the better way is the one described in this question: stackoverflow.com/questions/1171035/… I prefer not to redirect the user to a different URL because it is less user-friendly (even I find it annoying while developing). Cheers.
I'm getting the error Config Error: The configuration section 'customErrors' cannot be read because it is missing a section declaration.
7

Also you can handle NOT FOUND error in Global.asax.cs as below

protected void Application_Error(object sender, EventArgs e) { Exception lastErrorInfo = Server.GetLastError(); Exception errorInfo = null; bool isNotFound = false; if (lastErrorInfo != null) { errorInfo = lastErrorInfo.GetBaseException(); var error = errorInfo as HttpException; if (error != null) isNotFound = error.GetHttpCode() == (int)HttpStatusCode.NotFound; } if (isNotFound) { Server.ClearError(); Response.Redirect("~/Error/NotFound");// Do what you need to render in view } } 

Comments

4

Add this lines under your project root web.config File.

 <system.webServer> <httpErrors errorMode="Custom" existingResponse="Replace"> <remove statusCode="404" /> <error statusCode="404" responseMode="ExecuteURL" path="/Test/PageNotFound" /> <remove statusCode="500" /> <error statusCode="500" responseMode="ExecuteURL" path="/Test/PageNotFound" /> </httpErrors> <modules> <remove name="FormsAuthentication" /> </modules> 

1 Comment

Thank you this is what I needed. In case anyone falls into the same issue as me existingResponse="Replace" fixed it. I had Auto set in there before which is the suggested option in most posts. I guess auto in my case scenario was not able to determine to use replace.
3

This might be a problem when you use

throw new HttpException(404); 

When you want to catch that, I don't know any other way then editing your web config.

5 Comments

ActionFilters : use them to catch the HttpException.
What if the exception is not thrown by a controller action? I throw a 404 in my controller factory.
Not sure then - i'm not playing around with controller factories. soz.
Controllerfactory is not the only place where it can happen. I map a catch all route to an actionmethod that just throws the exception. The exception is handled by the web.config
Throw any Exception you want. Let all your controller derived from a BaseController. In this BaseController you override OnException and set the filterContext.Result either redirect or view result.
1

An alternative to creating a catch-all route is to add an Application_EndRequest method to your MvcApplication per Marco's Better-Than-Unicorns MVC 404 Answer.

Comments

1

Inside RouterConfig.cs add the follwing piece of code:

 routes.MapRoute( name: "Error", url: "{id}", defaults: new { controller = "Error", action = "PageNotFound" }); 

Comments

0

If the route cannot be resolved, then MVC framework will through 404 error.. Best approach is to use Exception Filters ... Create a custom exceptionfilter and make like this..

public class RouteNotFoundAttribute : FilterAttribute, IExceptionFilter { public void OnException(ExceptionContext filterContext) { filterContext.Result = new RedirectResult("~/Content/RouteNotFound.html"); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.