Inject DbContext to Custom IRouteConstraint in ASP.NET Core 2 MVC

asp.net-core-mvc asp.net-mvc-routing dependency-injection entity-framework-core

Question

I'm using ASP.NET Core 2. I'm attempting to inject the DbContext into a custom IRouteConstraint. However, it appears that the context is disposed of before it attempts to call the Match method. I'm sure I'm overlooking something really simple here. Any ideas how I can pass the context into the route constraint?

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));   
    ...
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ApplicationDbContext applicationDbContext)
{
    ...
    app.UseMvc(routes =>
    {
        // Route validation
        routes.MapRoute("routevalidation", "{*route}", new { controller = "Home", action = "Reroute" }, new { route = new ShinyNewRouteConstraint() });    
        ...
    });
}
1
0
10/12/2017 5:20:28 PM

Accepted Answer

Here is one way to do it (although not sure whether this is the best way):

ShinyNewRouteConstraint

public class ShinyNewRouteConstraint : IRouteConstraint
{
    private readonly Func<ApplicationDbContext> createDbContext;

    public ShinyNewRouteConstraint(Func<ApplicationDbContext> createDbContext)
    {
        this.createDbContext = createDbContext;
    }

    public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        using (var dbContext = createDbContext())
        {
           // Run a query...
           var users = dbContext.Users.ToList();

           // Constraint logic
        }

        return false;
    }
}

Usage

// Route validation
routes.MapRoute(
    "routevalidation", 
    "{*route}", 
    new { controller = "Home", action = "Reroute" }, 
    new { route = new ShinyNewRouteConstraint(() => 
    app.ApplicationServices.CreateScope().ServiceProvider.GetRequiredService<ApplicationDbContext>()) });

NOTE: I recommend using caching in this scenario because route constraints are matched on every request, which could easily flood your database with too many requests.

2
10/12/2017 8:45:36 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow