1

I am trying to handle the HTTP errors in a MVC5 site this way:

web.config:

<system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
      <clear/>
      <error statusCode="403" path="/language/Error/Details/403" responseMode="ExecuteURL"/>
      <error statusCode="404" path="/language/Error/Details/404" responseMode="ExecuteURL"/>
      <error statusCode="500" path="/language/Error/Details/500" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>

ErrorController.cs:

// GET: Error/Details
public ActionResult Details()
{
    /* Setting the language for the errors since it is not possible to handle multi-language errors in the web.config file where the errors are redirected */
    if (!CultureHelper.cultures.Contains(base.culture))
    {
        RouteData.Values["culture"] = CultureHelper.GetCurrentNeutralCulture();
    }

    /* Redirecting uncontrolled errors to 404 error */
    if (RouteData.Values["statusCode"] == null)
    {
        return RedirectToRoute(new { culture = base.culture, controller = "Error", action = "Details", statusCode = 404 });
    }

    /* Preparing the model */
    ErrorViewModel error = ErrorFactory.Create(Convert.ToInt32(RouteData.Values["statusCode"]));


    /* Preparing the view */
    base.SetLanguageFromRoute();

    return View(error);
}

RouteConfig.cs:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{culture}/{controller}/{action}/{id}",
        defaults: new { culture = CultureHelper.GetCurrentNeutralCulture(), controller = "User", action = "Home", id = UrlParameter.Optional }
    );

    routes.MapRoute(
        name: null,
        url: "{culture}/Error/Details/{statusCode}",
        defaults: new { culture = CultureHelper.GetCurrentNeutralCulture() }
    );
}

My problem is, when the Details GET action gets called, once it reaches this line:

if (RouteData.Values["statusCode"] == null)

It always returns true, because there's no "statusCode" key in RouteData since it's using the Default route instead of the Error route, and the statusCode gets passed in the route with the name "id" (default route key).

I know I could just use the default route and catch the Status Code from the ID, but I have that custom route for when I do a RedirectToRoute to an error from other controllers, so I would like to use it here. Is there any way to tell <httpErrors> that I want to use a different route from the Default one?

Nkosi
  • 235,767
  • 35
  • 427
  • 472
user3333069
  • 61
  • 1
  • 1
  • 3

1 Answers1

-1

Is there any way to tell that I want to use a different route from the Default one?

Yes. There are 2 ways.

The most sensible way is to put specific routes before general routes so you don't have unreachable execution paths in your route table. This ensures your incoming URLs are directed to the correct controller.

That means you need to put the more specific custom route before your default route so it will be checked first.

public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Error",
            url: "{culture}/Error/Details/{statusCode}",
            defaults: new { culture = CultureHelper.GetCurrentNeutralCulture() }
        );

        routes.MapRoute(
            name: "Default",
            url: "{culture}/{controller}/{action}/{id}",
            defaults: new { culture = CultureHelper.GetCurrentNeutralCulture(), controller = "User", action = "Home", id = UrlParameter.Optional }
        );
    }

The other way is to specify the route name when calling RedirectToRouteResult. Note that you didn't give your route a name (it is null) so there is no way for you to do this unless you name it as I have above.

return RedirectToRoute(
    routeName: "Error", 
    routeValues: new { culture = base.culture, controller = "Error", action = "Details", statusCode = 404 });

This will redirect you to the correct URL, but probably still won't function because when the URL is accessed it will still hit your "Default" route since it matches this URL and is registered first.

Community
  • 1
  • 1
NightOwl888
  • 55,572
  • 24
  • 139
  • 212