1

I have a asp.net mvc 3 application with IIS7 and IIS express on local, which is using Application_Error for logging the exceptions and redirecting to a custom error page. My application has different regions, and the application_error is called whenever the controller or the action is not matched, but not for the region.

Here is an example of the routes used:

routes.MapRoute(
            "Default",
            "{region}/{controller}/{action}/{id}",
            new { region = "uk", controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
            new { region = new RegionWhitelistConstraint() } // constraint for valid regions
        );

In this case the Application_Error would be fired for /uk/NotFoundPage but not for /foo/Home

Here the constraint for the region:

public class RegionWhitelistConstraint : IRouteConstraint
{
    public bool Match(System.Web.HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        var whiteList = Region.DefaultWhiteList;
        var currentRegionValue = values[parameterName].ToString();
        return whiteList.Contains(currentRegionValue);
    }
}

I have seen this question, that propose adding a catch all route, but apart from that I would like to know if there is a way of firing Application_Error as it is done for the controllers or actions.

Community
  • 1
  • 1
Markinhos
  • 736
  • 1
  • 6
  • 13

2 Answers2

2

You can throw an exception in your constraint class. This will be handled by Application_Error :

public class RegionWhitelistConstraint : IRouteConstraint
{
    public bool Match(System.Web.HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        var whiteList = Region.DefaultWhiteList;
        var currentRegionValue = values[parameterName].ToString();
        var match = whiteList.Contains(currentRegionValue);

        if (!match)
        {
            throw new HttpException(404, "Not Found");
        }

        return match;
    }
}
DareDude
  • 63
  • 1
  • 7
0

I figured out what was the problem: when a controller or an action is wrong they are still matched by the route system with the pattern:

        routes.MapRoute(
            "Default",
            "{region}/{controller}/{action}/{id}",
            new { region = "uk", controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
            new { region = new RegionWhitelistConstraint() } // constraint for valid regions
        );

but when the region is not in the whitelist it is not matched. This makes bypass the application_error. The solution that I have used is creating a catchall route:

        routes.MapRoute(
            "NotFound",
            "{*url}",
            new { region = "uk", controller = "Error", action = "NotFound", id = UrlParameter.Optional }
        );

and an action that raises an HttpException:

    [HttpGet]
    public ActionResult NotFound()
    {
        throw new HttpException(404, "Page not found");
    }
Markinhos
  • 736
  • 1
  • 6
  • 13