Request: allow dependency injection in RouteConstraints and IRouter
See original GitHub issueHi,
Problem
Currently, the registration of IRoute
and IRouteConstraint
implementations is not adapted for dependency injection. In order to add implementations of those, one needs to explicitly initialize them.
My request is that you allow registering them so that they are resolved by the container when required.
For instance, I’m working on a multi-tenant app, and I want to make sure tenant exists before we’re routing to controller etc. There is a catalog database containing the tenant info, and I’d want to break the routing if the tenant doesn’t exist in the catalog DB.
Solution
My request is that allow ‘registering’ IRouteContraint
s implementations so that they are resolved by the DI container, instead of registering their type in the dictionary.
For example:
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.Configure<RouteOptions>(options => {
// suggested:
options.ConstraintMap.Register<SubdomainConstraint>();
});
}
// SubdomainConstraint.cs
public class SubdomainConstraint : IRouteConstraint
{
// this provider uses the CatalogDbContext to check if tenant exists
readonly ITenantProvider _TenantProvider;
public SubdomainConstraint(ITenantProvider tenantProvider)
{
_TenantProvider = tenantProvider;
}
public bool Match(HttpContext httpContext, IRouter route, string routeKey,
RouteValueDictionary values, RouteDirection routeDirection)
{
return _TenantProvider.Tenant != null;
}
}
The same applies to IRouter
:
// Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMvc(routes =>
{
routes.Routes.Register<SubdomainRouter>();
});
}
// SubdomainRouter.cs
public class SubdomainRouter : IRouter
{
readonly IRouter _DefaultRouter;
readonly ITenantProvider _TenantProvider;
public SubdomainRouter(IRouter defaultRouter, ITenantProvider tenantProvider)
{
_DefaultRouter = defaultRouter;
_TenantProvider = tenantProvider;
}
public VirtualPathData GetVirtualPath(VirtualPathContext context) =>
_DefaultRouter.GetVirtualPath(context);
public Task RouteAsync(RouteContext context)
{
if (_TenantProvider.Tenant == null)
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
return _DefaultRouter.RouteAsync(context);
}
}
Issue Analytics
- State:
- Created 4 years ago
- Comments:10 (6 by maintainers)
@rynowak do we have a mechanism to achieve this?
Right. These have to be singletons.
If you want to participate in the request scope, use
HttpContext.RequestServices
to retrieve what you need.