Reputation: 1969
For a multi tenant application in ASP.NET MVC 5, I have created a custom IRouteConstraint to check if a subdomain exists in the base url, like client1.myapplication.com or client2.application.com.
public class TenantRouteConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
string appSetting = ConfigurationManager.AppSettings[AppSettings.IsMultiTenancyEnabled];
bool isMultiTenancyEnabled = false;
bool isParsedCorrectly = bool.TryParse(appSetting, out isMultiTenancyEnabled);
if (isMultiTenancyEnabled)
{
string subdomain = httpContext.GetSubdomain();
if (subdomain != null && !values.ContainsKey("subdomain"))
{
values.Add("subdomain", subdomain);
}
return string.IsNullOrEmpty(subdomain) ? false : true;
}
else
{
return true;
}
}
}
Here is the route config setup:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreWindowsLoginRoute();
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "Dime.Scheduler.WebUI.Controllers" },
constraints: new { TenantAccess = new TenantRouteConstraint() }
);
}
}
The route constraint works very well but I need to understand this process better. I want to know what happens exactly when this method below returns FALSE. The end result is a HTTP Error 403.14 - Forbidden page, but is there some way I can intercept this to present my own custom page? I usually capture these errors in the Global Asax file but in this case, it never gets there.
Could this have something to do with the fact that there won't be any routes that match the request? Is there any way to redirect to a custom page if no matches are found?
Upvotes: 1
Views: 825
Reputation: 56869
After any route constraint that is associated with the route returns false, the route is considered a non-match and the .NET routing framework will check the next route registered in the collection (the matching is performed in order from the first route down to the last route that is registered in the collection).
The end result is a HTTP Error 403.14 - Forbidden page, but is there some way I can intercept this to present my own custom page?
You can get more precise control over routing by inheriting RouteBase (or inheriting Route). There is a pretty good example of domain-based routing here.
The key to doing this is to make sure you implement both methods. GetRouteData
is where you analyze the request to determine if it matches and return a dictionary of route values if it does (and null if it doesn't). GetVirtualPath
is where you get a list of route values, and if they match you should (typically) return the same URL that was input in the GetRouteData
method that matched. GetVirtualPath
is called whenever you use ActionLink
or RouteLink
within MVC, so it is usually important that an implementation be provided.
You can determine the page that the route will direct to by simply returning the correct set of route values in GetRouteData
.
Upvotes: 1