Can I access a database during startup in ASP.NET Core?
Solution 1
Yes, you can access the database! Code that runs in the Configure
method can access any services that are added in the ConfigureServices
method, including things like database contexts.
For example, if you have a simple Entity Framework context:
using Microsoft.EntityFrameworkCore;
using SimpleTokenProvider.Test.Models;
namespace SimpleTokenProvider.Test
{
public class SimpleContext : DbContext
{
public SimpleContext(DbContextOptions<SimpleContext> options)
: base(options)
{
}
public DbSet<User> Users { get; set; }
}
}
And you add it in ConfigureServices
:
services.AddDbContext<SimpleContext>(opt => opt.UseInMemoryDatabase());
Then, you can access it when you are setting up the middleware:
var context = app.ApplicationServices.GetService<SimpleContext>();
app.UseSimpleTokenProvider(new TokenProviderOptions
{
Path = "/api/token",
Audience = "ExampleAudience",
Issuer = "ExampleIssuer",
SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256),
IdentityResolver = (username, password) => GetIdentity(context, username, password)
});
And rewrite the GetIdentity
method a little:
private Task<ClaimsIdentity> GetIdentity(SimpleContext context, string username, string password)
{
// Access the database using the context
// Here you'd need to do things like hash the password
// and do a lookup to see if the user + password hash exists
}
I'm the author of the original sample. Sorry it wasn't clear initially! I tried to write the IdentityResolver
delegate in a way that makes it easy to provide your own functionality -- like integrating with your own database (as above), or hooking it up to ASP.NET Core Identity. Of course, you're free to throw away my code and do something better, too. :)
Solution 2
On .NET CORE 2.1, just pass the context as an argument to the Configure method:
public void Configure(IApplicationBuilder app, YourDbContext context, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//do whatever you want with the context here...
}
Adding services to the service container makes them available within the app and in the Configure method. The services are resolved via dependency injection or from ApplicationServices.
Solution 3
The accepted answer does not work for scoped services (scoped services are created per request, if you are using Entity Framework and adding the context with AddDbContext
then this is the case).
You can use scoped services in startup as follows (source):
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
using (var serviceScope = app.ApplicationServices.CreateScope())
{
var services = serviceScope.ServiceProvider;
var myDbContext = services.GetService<MyDbContext>();
}
}
or pass it in the argument of the Configure
method as shown in the answer of
juanora
Related videos on Youtube
Top Rat
Updated on September 18, 2020Comments
-
Top Rat over 3 years
I have recently been working on a .NET Core web API. I have just attempted authentication using JWT, by following the guide on https://stormpath.com/blog/token-authentication-asp-net-core.
All was going well until I had to replace the hard-coded username and passwords in the
GetIdentity
method with a DB query and realized I do not know how to access the DB from within this file!The method I am referring to is shown in the link below on line 70. https://github.com/nbarbettini/SimpleTokenProvider/blob/master/test/SimpleTokenProvider.Test/Startup.Auth.cs
My questions are as follows.
- Can I access the database here? If so how?
- Should this be where the GetIdentity method is, or is there a better way?
-
xcud over 7 yearsIf you're just adding JWT to aspnet identity, you may pass the signinmanager instead of the dbcontext: var userManager = app.ApplicationServices .GetService(typeof(UserManager<ApplicationUser>))
-
Mohamed Badr over 6 years@xcud That's exactly what I'm trying to do but get an error " Cannot resolve scoped service 'Microsoft.AspNetCore.Identity.UserManager`", what am I missing here?
-
CopyJosh about 6 yearsShould update the sample or add this concept in comments, this was driving me crazy for hours! Thank you for your answer!
-
Florian Moser over 5 yearsThis does not work for scoped services. If you've used
AddDbContext
with Entity Framework then your DB service is scoped. Check out my answer for a solution. -
Marvin over 5 yearsI think this is the recommended way to consume scoped services in singletons and services, reference sample code: consuming-a-scoped-service-in-a-background-task
-
Legends over 4 yearsThis is the actual and simplest answer, provided you have registered your
DbContext
withDI
upfront or implicitly withAddDbContext
. Working at least from.net core 2.1
as stated in this answer (Didn't check it, works with 3.0 prev) -
jegtugado over 4 yearsMay I ask if you registered a service as scoped, can you still access it within the
Configure
method or only transients and singletons work here? -
juanora over 4 years@jegtugado is supposed to work. Btw AddDbContext adds as scoped
-
Tom McDonough over 4 years@xcud you need to add Identity to the services, for example services.AddIdentity<User, Role>() will add User and Role so you are able to use throughout your application