[asp.net] Routing for custom ASP.NET MVC 404 Error page

I am trying to make a custom HTTP 404 error page when someone types in a URL that doesn't invoke a valid action or controller in ASP.NET MVC, instead of it displaying the generic "Resource Not Found" ASP.NET error.

I don't want to use the web.config to handle this.

Is there any kind of routing magic I can do to catch any invalid URLs?

Update: I tried the answer given, however I still get the ugly "Resource Not Found" message.

Another update: Ok, apparently something changed in RC1. I've even tried specifically trapping 404 on an HttpException and it still just gives me the "Resource Not Found" page.

I've even used MvcContrib's resource's feature and nothing - same problem. Any ideas?

The answer is


Source

NotFoundMVC - Provides a user-friendly 404 page whenever a controller, action or route is not found in your ASP.NET MVC3 application. A view called NotFound is rendered instead of the default ASP.NET error page.

You can add this plugin via nuget using: Install-Package NotFoundMvc

NotFoundMvc automatically installs itself during web application start-up. It handles all the different ways a 404 HttpException is usually thrown by ASP.NET MVC. This includes a missing controller, action and route.

Step by Step Installation Guide :

1 - Right click on your Project and Select Manage Nuget Packages...

2 - Search for NotFoundMvc and install it. enter image description here

3 - Once the installation has be completed, two files will be added to your project. As shown in the screenshots below.

enter image description here

4 - Open the newly added NotFound.cshtml present at Views/Shared and modify it at your will. Now run the application and type in an incorrect url, and you will be greeted with a User friendly 404 page.

enter image description here

No more, will users get errors message like Server Error in '/' Application. The resource cannot be found.

Hope this helps :)

P.S : Kudos to Andrew Davey for making such an awesome plugin.


Try this in web.config to replace IIS error pages. This is the best solution I guess, and it sends out the correct status code too.

<system.webServer>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" subStatusCode="-1" />
    <remove statusCode="500" subStatusCode="-1" />
    <error statusCode="404" path="Error404.html" responseMode="File" />
    <error statusCode="500" path="Error.html" responseMode="File" />
  </httpErrors>
</system.webServer>

More info from Tipila - Use Custom Error Pages ASP.NET MVC


Here is true answer which allows fully customize of error page in single place. No need to modify web.config or create separate code.

Works also in MVC 5.

Add this code to controller:

        if (bad) {
            Response.Clear();
            Response.TrySkipIisCustomErrors = true;
            Response.Write(product + I(" Toodet pole"));
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            //Response.ContentType = "text/html; charset=utf-8";
            Response.End();
            return null;
        }

Based on http://www.eidias.com/blog/2014/7/2/mvc-custom-error-pages


If you work in MVC 4, you can watch this solution, it worked for me.

Add the following Application_Error method to my Global.asax:

protected void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    Server.ClearError();

    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "Error");
    routeData.Values.Add("action", "Index");
    routeData.Values.Add("exception", exception);

    if (exception.GetType() == typeof(HttpException))
    {
        routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
    }
    else
    {
        routeData.Values.Add("statusCode", 500);
    }

    IController controller = new ErrorController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();

The controller itself is really simple:

public class ErrorController : Controller
{
    public ActionResult Index(int statusCode, Exception exception)
    {
        Response.StatusCode = statusCode;
        return View();
    }
}

Check the full source code of Mvc4CustomErrorPage at GitHub.


I will talk about some specific cases,

if you are using 'PageNotFound method' in HomeController like below

[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

it wouldn't work this. But you must clear Route tags like below,

//[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

And if you change it as method Name in web.config it works. However don't forget to do code like below in web.config

<customErrors mode="On">
  <error statusCode="404" redirect="~/PageNotFound" /> 
 *// it is not "~/404" because it is not accepted url in Route Tag like [Route("404")]*
</customErrors>

This solution doesn't need web.config file changes or catch-all routes.

First, create a controller like this;

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Title = "Regular Error";
        return View();
    }

    public ActionResult NotFound404()
    {
        ViewBag.Title = "Error 404 - File not Found";
        return View("Index");
    }
}

Then create the view under "Views/Error/Index.cshtml" as;

 @{
      Layout = "~/Views/Shared/_Layout.cshtml";
  }                     
  <p>We're sorry, page you're looking for is, sadly, not here.</p>

Then add the following in the Global asax file as below:

protected void Application_Error(object sender, EventArgs e)
{
        // Do whatever you want to do with the error

        //Show the custom error page...
        Server.ClearError(); 
        var routeData = new RouteData();
        routeData.Values["controller"] = "Error";

        if ((Context.Server.GetLastError() is HttpException) && ((Context.Server.GetLastError() as HttpException).GetHttpCode() != 404))
        {
            routeData.Values["action"] = "Index";
        }
        else
        {
            // Handle 404 error and response code
            Response.StatusCode = 404;
            routeData.Values["action"] = "NotFound404";
        } 
        Response.TrySkipIisCustomErrors = true; // If you are using IIS7, have this line
        IController errorsController = new ErrorController();
        HttpContextWrapper wrapper = new HttpContextWrapper(Context);
        var rc = new System.Web.Routing.RequestContext(wrapper, routeData);
        errorsController.Execute(rc);

        Response.End();
}

If you still get the custom IIS error page after doing this, make sure the following sections are commented out(or empty) in the web config file:

<system.web>
   <customErrors mode="Off" />
</system.web>
<system.webServer>   
   <httpErrors>     
   </httpErrors>
</system.webServer>

I've tried to enable custom errors on production server for 3 hours, seems I found final solution how to do this in ASP.NET MVC without any routes.

To enable custom errors in ASP.NET MVC application we need (IIS 7+):

  1. Configure custom pages in web config under system.web section:

    <customErrors mode="RemoteOnly"  defaultRedirect="~/error">
        <error statusCode="404" redirect="~/error/Error404" />
        <error statusCode="500" redirect="~/error" />
    </customErrors>
    

    RemoteOnly means that on local network you will see real errors (very useful during development). We can also rewrite error page for any error code.

  2. Set magic Response parameter and response status code (in error handling module or in error handle attribute)

      HttpContext.Current.Response.StatusCode = 500;
      HttpContext.Current.Response.TrySkipIisCustomErrors = true;
    
  3. Set another magic setting in web config under system.webServer section:

    <httpErrors errorMode="Detailed" />
    

This was final thing that I've found and after this I can see custom errors on production server.


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"

I had the same problem, the thing you have to do is, instead of adding the customErrors attribute in the web.config file in your Views folder, you have to add it in the web.config file in your projects root folder


Examples related to asp.net

RegisterStartupScript from code behind not working when Update Panel is used You must add a reference to assembly 'netstandard, Version=2.0.0.0 No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization How to use log4net in Asp.net core 2.0 Visual Studio 2017 error: Unable to start program, An operation is not legal in the current state How to create roles in ASP.NET Core and assign them to users? How to handle Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause() ASP.NET Core Web API Authentication Could not load file or assembly 'CrystalDecisions.ReportAppServer.CommLayer, Version=13.0.2000.0 WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping for jquery

Examples related to asp.net-mvc

Using Lato fonts in my css (@font-face) Better solution without exluding fields from Binding Vue.js get selected option on @change You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to send json data in POST request using C# VS 2017 Metadata file '.dll could not be found The default XML namespace of the project must be the MSBuild XML namespace How to create roles in ASP.NET Core and assign them to users? The model item passed into the dictionary is of type .. but this dictionary requires a model item of type How to use npm with ASP.NET Core

Examples related to asp.net-mvc-routing

How to correctly use Html.ActionLink with ASP.NET MVC 4 Areas ASP.NET MVC - Extract parameter of an URL The view 'Index' or its master was not found. Set "Homepage" in Asp.Net MVC Routing for custom ASP.NET MVC 404 Error page

Examples related to http-status-code-404

Tomcat 404 error: The origin server did not find a current representation for the target resource or is not willing to disclose that one exists Vue-router redirect on page not found (404) Apache: The requested URL / was not found on this server. Apache Tomcat Servlet: Error 404 - The requested resource is not available Django, creating a custom 500/404 error page TOMCAT - HTTP Status 404 Object not found! The requested URL was not found on this server. localhost Getting 404 Not Found error while trying to use ErrorDocument Servlet returns "HTTP Status 404 The requested resource (/servlet) is not available" MIME types missing in IIS 7 for ASP.NET - 404.17

Examples related to custom-error-pages

Rewrite URL after redirecting 404 error htaccess How to specify the default error page in web.xml? Implementing a Custom Error page on an ASP.Net website Routing for custom ASP.NET MVC 404 Error page ASP.NET custom error page - Server.GetLastError() is null