Search code examples
c#asp.net-core.net-coredbcontext

Efficiently newing up DbContext without dependency injection


I'd like to write a ClaimsPrincipal extension that returns the company associated with a user has the IsLimited flag set.

public static class ClaimsPrincipalExtensions
{
    public static bool IsLimitedUser(this ClaimsPrincipal principal)
    {
        ArgumentNullException.ThrowIfNull(principal);
        var claim = principal.FindFirst(ClaimTypes.NameIdentifier);
        if (claim != null)
        {
            return dbContext.Users
                .Where(u => u.Id == claim.Value)
                .Select(u => u.Facility.Company.IsLimited)
                .FirstOrDefault();
        }
        return false;
    }
}

But how do I initialize dbContext in the code above?

I am looking at calling this method from my _Layout.cshtml page, so it would be called on every single page request so I want it as optimized as possible. In fact, if possible, I'd like to cache the value with the ClaimsPrincipal. Anyway, I'd still need the DbContext the first time.


Solution

  • For using the dbcontext inside the static class, you need use the method injection, you should modify your method to add new parameter IServiceProvider and then pass it from the layout page.

    More details, you could refer to below codes:

    public static class ClaimsPrincipalExtensions
    {
    
    
        public static bool IsLimitedUser(this ClaimsPrincipal principal, IServiceProvider serviceProvider)
        {
            ArgumentNullException.ThrowIfNull(principal);
    
       
            // Resolve DbContext from the service provider
            using (var scope = serviceProvider.CreateScope())
            {
                var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();  
                var claim = principal.FindFirst(ClaimTypes.NameIdentifier);
                if (claim != null)
                {
                    //// Query the database
                    //bool isLimited = dbContext.Users
                    //    .Where(u => u.Id == claim.Value)
                    //    .Select(u => u.Facility.Company.IsLimited)
                    //    .FirstOrDefault();
    
    
                    var test = dbContext.Users.ToList();
                     bool isLimited = true;
    
                    return isLimited;
                }
            }
    
            return false;
        }
    }
    

    Layout:

    @using Microsoft.Extensions.DependencyInjection
    @inject IServiceProvider ServiceProvider
    
    ...
    
    @{
    
        var isLimitedUser = User.IsLimitedUser(ServiceProvider);
    }
    
    
    @if (isLimitedUser)
    {
        <p>User has limited access.</p>
    }
    else
    {
        <p>User has full access.</p>
    }
    

    Result:

    enter image description here