1

I have an ApplicationDbContext class : ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string> where I have override methods on SaveChanges && SaveChangesAsync to include the UpdateAuditEntities method. What i want is to get the user-name / email of the logged in user so every entity that inherits from IAuditableEntity is tagged with the user who created / updated the entity.

 private void UpdateAuditEntities() { var CurrentUserId = ???; var modifiedEntries = ChangeTracker.Entries() .Where(x => x.Entity is IAuditableEntity && (x.State == EntityState.Added || x.State == EntityState.Modified)); foreach (var entry in modifiedEntries) { var entity = (IAuditableEntity)entry.Entity; DateTime now = DateTime.UtcNow; if (entry.State == EntityState.Added) { entity.CreatedDate = now; entity.CreatedBy = CurrentUserId; } else { base.Entry(entity).Property(x => x.CreatedBy).IsModified = false; base.Entry(entity).Property(x => x.CreatedDate).IsModified = false; } entity.UpdatedDate = now; entity.UpdatedBy = CurrentUserId; } } 

Doing my research, i found a good article here but I have a DesignTimeDbContextFactory implementation like below:

public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext> { public ApplicationDbContext CreateDbContext(string[] args) { Mapper.Reset(); IConfigurationRoot configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .AddJsonFile("appsettings.Development.json", optional: true) .Build(); var builder = new DbContextOptionsBuilder<ApplicationDbContext>(); //IUserResolverService userResolverService = ServiceProviderServiceExtensions.CreateScope() builder.UseSqlServer(configuration["ConnectionStrings:DefaultConnection"], b => b.MigrationsAssembly("SybrinApp.Pro")); return new ApplicationDbContext(builder.Options); } } 

The suggested solution means my ApplicationDbContext will need UserResolverService to instantiate. How can i go about injecting UserResolverService into the DesignTimeDbContextFactory implementation or is there another way to get the currently logged in user in my class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>

2
  • Where are you using ApplicationUser class? in controller? Commented Feb 7, 2019 at 13:46
  • Sorry, i don't understand your question. Do you mean where am I trying to access the ApplicationUser from? I want the user info in my override methods. public override int SaveChanges() { UpdateAuditEntities(); return base.SaveChanges(); } the UpdateAuditEntities method is the one posted in the question. So this is in the ApplicationDbContext class which is am implementation of IdentityDbContext Commented Feb 7, 2019 at 13:53

1 Answer 1

1

OK, have changed my answer. I have borrowed from this url to demonstrate what you can do.

1) first of all create a DependencyResolver class to wrap up the DI Note that I am assuming that your userResolveService is implementing an IUserResolveService

 public class DependencyResolver { public IServiceProvider ServiceProvider { get; } public string CurrentDirectory { get; set; } public DependencyResolver() { // Set up Dependency Injection IServiceCollection services = new ServiceCollection(); ConfigureServices(services); ServiceProvider = services.BuildServiceProvider(); } private void ConfigureServices(IServiceCollection services) { // Register any DI you need here services.AddTransient<IUserResolverService, UserResolverService>(); } } 

2) In your DesignTimeDbContextFactory, replace the commented out line with:

var resolver = new DependencyResolver(); IUserResolverService svc = resolver.ServiceProvider.GetService(typeof(IUserResolverService)) as UserResolverService; 

Then go ahead and call as you need

Sign up to request clarification or add additional context in comments.

2 Comments

this won't work as SaveChanges has an implementation in IdentityDbContext which am just overriding meaning i can't pass parameters / change SaveChanges' signature. Unless i am missing something.
Thanks, this works. Just had to add the services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); to the ConfigureServices method.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.