Closed dazinator closed 6 years ago
Hope it will be available asap.
There is a working sample in my feature/routing branch. The tenant container and middleware pipeline are still set up in configureservices, but its now the asp.net router that is configured in Configure() method rather than adding dotnettency middleware. Im still exploring it as an idea but it seems to work fine.
Closing this. Leaving routing in branch.
Having read more about Routing I am considering some changes to make multitenancy features a part of routing.
Custom
IRouter
s could potentially be used to:Idea being;
RouterMiddleware
firesRouterMiddleware
middleware loops through it'sRouteCollection
calling RouteAsync() on each IRouter in the collection, until one of them sets aHandler
on theRouteContext
. If no handler is set, then thenext
middleware in the chain is invoked as normal.I am considering having the following custom
IRouter
implementations that you could add to aRouteCollection
.ContainerRouter
When this Router has
RouteAsync
invoked, it will:IApplicationBuilder.ApplicationServices
for the current container. ~~MiddlewareRouter
When this Router has
RouteAsync
invoked, it will lazy initialise aRequestDelegate
representing a MiddlewarePipeline. When it creates the RequestDelegate it will fork the root IApplicationBuilder instance, and it will swap out theApplicationServices
on the forked instance for the current containersIServiceProvider
. This ensures that middleware in the pipeline has access only to services from the current resolved container.For this to work, the ContainerRouter should be ahead of the MiddlewareRouter. This is so that the appropriate container is resolved, prior to the middleware pipeline being lazy initialised - ensuring that when the middleware is created, it gets access to the services from the currently resolved container.
Order of events are roughly:
Note: When the middleware pipeline is invoked at the last step - the whole process could be nested.
Benefits?
I can potentially remove custom dotnettency middleware, and rely on single Routing middleware with custom routers instead. i.e
routes.MapContainer()
androutes.MapMiddlewarePipeline()
extension methods could take the pace of custom middleware.The ContainerRouter, could be optionally configured to only restore some container if a route template matched. i.e
nest
to form a hierarchy of environments and subsystems if required e.g:Request --> RouterMiddleware (Application A) --> ContainerRouter, MiddlewareRouter --> Middleware Pipeline --> |NESTING begins| RouterMiddleware (Subsystem A) --> ContainerRouter, MiddlewareRouter --> Middleware Pipeline
In the above scenario, a request is received by router middleware, and the dotnettency container router restores a container for the matching route / httprequest, before allowing the dotnettency middleware router to resolve a RequestDelegate (middleware pipeline) for the request. The router RouterMiddleware then invokes the RequestDelegate for the middleware pipeline - allowing the request to flow through Application A's middleware. In the middleware pipeline for Application A, we nest the whole process again for "Subsystem A". Subsystem A for example, may have a ContainerRouter and MiddlewareRouter that only matches on specific URL's / endpoints related to subsystem A. For example, an MVC Controller that should be isolated from other services could have its own ContainerRouter. Also perhaps it requires middleware only for this endpoint i.e the url is
/SubsystemA/Foo
.Note: If there is more than one ContainerRouter added to a RouteCollection there is a "last one wins" scenario.
A ContainerRouter will never handle a Request as it will never set RouteContext.Handler. However it may add itself to RouteContext.Routers or add DataTokens to the RouteContext when it successfully restores a container.