ASP.NET Core 2.2 get userId in DbContext

asp.net-core asp.net-identity c# entity-framework entity-framework-core

Question

I am quite new to ASP.NET Core. I want to create ASP.NET Core 2.2 WebAPI, with Entity Framework Core and ASP.NET Identity. Also, I want to use JWT to secure access to that WebAPI with tokens.

I have successfully managed to insert user to DB and to get token back from my API, and token auth is working.

But, I also want to soft delete database records and to keep track on who has deleted/updated/added a record. Test table for that is Countries, where fields are only Title and Description.

So far, I have turned Internet upside-down, but no help :(

Las thing that I have tried is (userId is null):

  • In startup.cs:

    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    
  • in my AppDbContext.cs

    public class AppDbContext : IdentityDbContext<AppUser>{
    
        public AppDbContext(DbContextOptions options) : base(options)
        {
        }
    
        public DbSet<AppUser> AppUsers { get; set; }
    
        public DbSet<Country> Countries { get; set; } // just for testing
    
        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
    
            // TODO - IGNORE THIS
            //builder.Entity<AppUser>().Property<bool>("IsDeleted");
            //builder.Entity<AppUser>().HasQueryFilter(m => EF.Property<bool>(m, "IsDeleted") == false);
        }
    
        public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            CheckBeforeSaving();
            return (await base.SaveChangesAsync(true, cancellationToken).ConfigureAwait(false));
        }
    
        private void CheckBeforeSaving()
        {
            var httpContextAccessor = this.GetService<IHttpContextAccessor>();
            var userId = httpContextAccessor?.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
    
            foreach (var entry in ChangeTracker.Entries())
            {
                switch (entry.State)
                {
                    case EntityState.Detached:
                        break;
                    case EntityState.Unchanged:
                        break;
                    case EntityState.Deleted:
                        entry.State = EntityState.Modified;
                        entry.CurrentValues["IsDeleted"] = true;
                        entry.CurrentValues["DeletedBy"] = userId;
                        entry.CurrentValues["Deleted"] = DateTime.Now;
                        break;
                    case EntityState.Modified:
                        entry.CurrentValues["UpdatedBy"] = userId;
                        entry.CurrentValues["Updated"] = DateTime.Now;
                        break;
                    case EntityState.Added:
                        entry.CurrentValues["IsDeleted"] = false;
                        entry.CurrentValues["CreatedBy"] = userId;
                        entry.CurrentValues["Created"] = DateTime.Now;
                        entry.CurrentValues["Description"] = userId;
                        break;
                    default:
                        break;
                }
            }
        }}}
    
1
1
10/20/2019 2:48:33 PM

Accepted Answer

Try to inject IHttpContextAccessor into the ApplicationDbContext directly:

public class ApplicationDbContext : IdentityDbContext<AppUser>
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IHttpContextAccessor httpContextAccessor)
        : base(options)
    {
        _httpContextAccessor= httpContextAccessor;
    }

    //other methods

   private void CheckBeforeSaving()
   {        
     var userId = _httpContextAccessor?.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
     //...
   }
}
1
8/22/2019 9:09:14 AM

Popular Answer

private async Task<ApplicationUser> GetUserDetailsAnsyc()
{
  return await userManager.GetUserAnsync(HttpContext.User);
}

var user = await GetUserDetailsAnsyc();
Console.WriteLine(user.Id.ToString());


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