1

I have a custom route set up:

var tradeCategoriesRoute = routes.MapRoute(
     name: "TradeCategoriesIndex",
     url: "TradeCategories/{*categories}",
     defaults:
          new
          {
                controller = "TradeCategories",
                action = "Index"
          },
          namespaces: new[] {"Website.Controllers"}
);
tradeCategoriesRoute.DataTokens["UseNamespaceFallback"] = false;
tradeCategoriesRoute.RouteHandler = new CategoriesRouteHandler();

I also have a custom 404 page set up in my Global.asax:

private void Application_Error(object sender, EventArgs e)
{
    var exception = Server.GetLastError();
    var httpException = exception as HttpException;
    DisplayErrorPage(httpException);
}

private void DisplayErrorPage(HttpException httpException)
{
    Response.Clear();
    var routeData = new RouteData();

    if (httpException != null && httpException.GetHttpCode() == 404)
    {
        routeData.Values.Add("controller", "Error");
        routeData.Values.Add("action", "Missing");
    }
    else if (httpException != null && httpException.GetHttpCode() == 500)
    {
        routeData.Values.Add("controller", "Error");
        routeData.Values.Add("action", "Index");
        routeData.Values.Add("status", httpException.GetHttpCode());
    }
    else
    {
        routeData.Values.Add("controller", "Error");
        routeData.Values.Add("action", "Index");
        routeData.Values.Add("status", 500);
    }
    routeData.Values.Add("error", httpException);
    Server.ClearError();
    Response.TrySkipIisCustomErrors = true;
    IController errorController = ObjectFactory.GetInstance<ErrorController>();
    errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();
}

It seems that my real problem is the custom route handler that I made:

public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
    IRouteHandler handler = new MvcRouteHandler();
    var values = requestContext.RouteData.Values;
    if (values["categories"] != null)
        values["categoryNames"] = values["categories"].ToString().Split('/').Where(x => !string.IsNullOrWhiteSpace(x)).ToArray();
    else
        values["categoryNames"] = new string[0];
    return handler.GetHttpHandler(requestContext);
}

It works fine and properly displays the 404 page for routes like "/doesnotexist" but doesn't work for routes like "/TradeCategories/doesnotexist". Instead I get a built in 404 page with the message "The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.".

How can I get my custom 404 page working with these custom routes?

jdehlin
  • 10,909
  • 3
  • 22
  • 33

2 Answers2

1

Something you might want to look into is your implementation for the TradeCategories Controller's Index action. The custom route and custom handler look like they'll match basically any route (TradeCategories/*), so I'm guessing something in your action or view is returning a 404 without throwing an exception that can be caught in global.asax?

psantiago
  • 695
  • 6
  • 16
0

You need to override the Application_Error method in you GLobal.asax

From the link:

void Application_Error(object sender, EventArgs e)
{
  // Code that runs when an unhandled error occurs

  // Get the exception object.
  Exception exc = Server.GetLastError();

  // Handle HTTP errors
  if (exc.GetType() == typeof(HttpException))
  {
    // The Complete Error Handling Example generates
    // some errors using URLs with "NoCatch" in them;
    // ignore these here to simulate what would happen
    // if a global.asax handler were not implemented.
      if (exc.Message.Contains("NoCatch") || exc.Message.Contains("maxUrlLength"))
      return;

    //Redirect HTTP errors to HttpError page
    Server.Transfer("HttpErrorPage.aspx");
  }

  // For other kinds of errors give the user some information
  // but stay on the default page
  Response.Write("<h2>Global Page Error</h2>\n");
  Response.Write(
      "<p>" + exc.Message + "</p>\n");
  Response.Write("Return to the <a href='Default.aspx'>" +
      "Default Page</a>\n");

  // Log the exception and notify system operators
  ExceptionUtility.LogException(exc, "DefaultPage");
  ExceptionUtility.NotifySystemOps(exc);

  // Clear the error from the server
  Server.ClearError();
}

This should work. However, I would rather redirect to a different page, instead of writing to the Response.

Something like this:

IController controller = new ErrorPageController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();
Community
  • 1
  • 1
Cacho Santa
  • 6,846
  • 6
  • 41
  • 73
  • I should have been more explicit in my question. I have a custom 404 page set up using Application_Error. The problem is it doesn't work for urls that start with /TradeCategories as defined by my custom route. It only works for any route that doesn't start with /TradeCategories. – jdehlin Oct 15 '15 at 03:03
  • @jdehlin add a breakpoint in the function Application_Error( ), you should see a 404 error in there when trying to access /TradeCategories/NonExistingUrl – Cacho Santa Oct 15 '15 at 18:43
  • That's the problem. It doesn't hit Application_Error. I get this http://screencast.com/t/2snbcwL8t. I think it's not going through the pipeline if it matches that custom route for whatever reason. – jdehlin Oct 15 '15 at 19:10