Controller Folder Location Route Constraint

Recently I came across a scenario on my current project where we needed a webApiRoute to only be applicable to controllers in a specific folder. At first I was thinking I have to build a constraint to only allow a match on a route if the controller was in a specific virtual directory. Then it dawned on me the controllers aren’t in any virtual directory at all, they are not deployed, they are compiled into the application!

Lucky for me our folders match our namespace structure. Based on this I was able to create a custom constraint making sure the requested controller had a namespace that ended with the desired folder path. Ends up looking like below:

  public class NameSpaceConstraint : IHttpRouteConstraint
    {
        private string _nameSpace;

        public NameSpaceConstraint(string nameSpace)
        {
            this._nameSpace= nameSpace;
        }

        public bool Match(System.Net.Http.HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection)
        {
            if (!values.ContainsKey("Controller"))
            {
                return false;
            }
          
            string controllerName = values["Controller"].ToString();

            Type typeOfController = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.Name == controllerName + "Controller");

            return typeOfController != null && typeOfController.Namespace.EndsWith(this._nameSpace, StringComparison.CurrentCultureIgnoreCase);
        }
    }

Works well, just need to define route with constraint in startup and all is well:

  public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
               name: "FolderName",
               routeTemplate: "api/FolderName/{controller}/{id}",
               defaults: new { id = RouteParameter.Optional },
               constraints: new { NameSpace= new NameSpaceConstraint(".FolderName") }
               );
}

Of course this is assuming that my controller is in the same assembly that is executing my route constraint. If this wasn’t the case I’d have to get a little more crafty looking for types. Not an issue at this point, however.