Hi @Nandini S,
CANNOT consume scoped from singlleton service
From your description, I'm assuming you want to use the DbContext or UserManager in a Singleton service, right?
By default. in asp.net core identity, the DbContext
and UserManager
instance are typically scoped to the lifetime of a request. If we access the Scoped service from a Singleton service, it will show the "CANNOT consume scoped from singlleton service" error.
To solve this issue, in the Singleton service, we can access them via the IServiceProvider
or IServiceScopeFactory
, refer to the following sample code:
TestSingletonService.cs:
using Microsoft.AspNetCore.Identity;
using WebApplication1.Data;
namespace WebApplication1.Services
{
public interface ITestSingletonService
{
IdentityUser GetUserViaProvider();
IdentityUser GetUserViaScopeFactory();
IdentityUser GetUserViaUserManager();
}
public class TestSingletonService:ITestSingletonService
{
private readonly IHttpContextAccessor _httpContextAccessor; //inject the httpcontext to get the current login user.
private readonly IServiceProvider _serviceProvider; //get the dbcontext via the IServiceProvider.
private readonly IServiceScopeFactory _serviceScopeFactory; //get the dbcontext via the IServiceScoptFactory.
public TestSingletonService(IHttpContextAccessor httpContextAccessor,
IServiceProvider serviceProvider,
IServiceScopeFactory serviceScopeFactory)
{
_httpContextAccessor = httpContextAccessor;
_serviceProvider = serviceProvider;
_serviceScopeFactory = serviceScopeFactory;
}
public IdentityUser GetUserViaProvider()
{
using (var scope = _serviceProvider.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
// Use dbContext here
return dbContext.Users.Where(c => c.UserName == _httpContextAccessor.HttpContext.User.Identity.Name).FirstOrDefault();
}
}
public IdentityUser GetUserViaScopeFactory()
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
// Use dbContext here
return dbContext.Users.Where(c => c.UserName == _httpContextAccessor.HttpContext.User.Identity.Name).FirstOrDefault();
}
}
public IdentityUser GetUserViaUserManager()
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>();
var user = userManager.FindByNameAsync(_httpContextAccessor.HttpContext.User.Identity.Name).Result;
return user;
}
}
}
}
Then, in the Program.cs file, register the service:
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();
builder.Services.AddHttpContextAccessor();
builder.Services.AddSingleton<ITestSingletonService, TestSingletonService>();
In the MVC controller, we can access the singleton service like this:
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly ITestSingletonService _singletonservice;
public HomeController(ILogger<HomeController> logger, ITestSingletonService testSingletonService)
{
_logger = logger;
_singletonservice= testSingletonService;
}
public IActionResult Privacy()
{
var user1 = _singletonservice.GetUserViaProvider();
var user2 = _singletonservice.GetUserViaScopeFactory();
var user3 = _singletonservice.GetUserViaUserManager();
return View();
}
The result as below:
If I misunderstand, please share your code to reproduce the problem.
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
Best regards,
Dillion