dazinator / Dotnettency

Mutlitenancy for dotnet applications
MIT License
111 stars 23 forks source link

TenantMatch IRouteConstraint ? #48

Closed dazinator closed 5 years ago

dazinator commented 5 years ago

It would be nice, if Dotnettency provided custom IRouteConstraint's that could be used to allow a route to match only if the current tenant matched some predicate check. I believe the IRouteConstraint concept exists in all the key paradigms that dotnettency will support in the upcoming release: (Asp.net core, OWIN (web api, etc), System.Web MVC)

Such that you could do things like this:


 public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {          

            routes.MapRoute(
                "Admin",
                "Admin/{action}",
                new {controller="Admin"},
                new {tenantConstraint =new TenantMatchConstraint<Tenant>(tenant=>tenant.Name == "Foo")}
            );

        }
        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
        }
    }

Note that, the route constraint, during request processing and URL evaluation, would resolve the current tenant, and then pass it to a Predicate check. The route will match if the predicate returns true. You can pass in the predicate

This allows for scenarios such as the following:

routes.MapRoute(
               "Default",                                              // Route name
               "{controller}/{action}/{id}",                   // URL with parameters
                new { controller = "Home", action = "Index", id = "" }, // Parameter defaults
                new {tenantConstraint = new TenantMatchConstraint<Tenant>(tenant != null)}
            );

 routes.MapRoute(
                "Welcome New Tenant",
                "Tenant/Welcome",
                new {controller="Tenant"},
                new {tenantConstraint =new TenantMatchConstraint<Tenant>(tenant == null)}
            );

The example above will route NULL tenants to a default landing page, allowing the default route for MVC to only match when there is a current tenant resolved.

This idea still needs some thought, as you can conceptually achieve this using per-tenant middleware pipelines - Add a router to each tenants own http middleware pipeline, and configure its routes accordingly. One potential issue with that approach is that it means MVC has to sit in each tenants pipeline and I am not sure if MVC is geared for that. Needs some more research.

https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/creating-a-custom-route-constraint-cs

https://docs.microsoft.com/en-gb/dotnet/api/microsoft.aspnetcore.routing.irouteconstraint?view=aspnetcore-2.2

dazinator commented 5 years ago

https://www.c-sharpcorner.com/UploadFile/ff2f08/custom-route-constraints-in-Asp-Net-mvc-5/

dazinator commented 5 years ago

https://www.hanselman.com/blog/AddingACustomInlineRouteConstraintInASPNETCore10.aspx

dazinator commented 5 years ago

https://andrewlock.net/using-routing-datatokens-in-asp-net-core/

dazinator commented 5 years ago

Need to consider this in context of Endpoint routing which is the new paradigm.

dazinator commented 5 years ago

No immediate need for this.