问题
I'm looking for the best way to track the Author and Editor fields for all the entities in my database.
I started by creating a base model which all my models inherit from:
public class DatabaseEntity
{
[Key]
public int Id { get; set; }
[Display(Name = "Last Modified By")]
public ApplicationUser Editor { get; set; }
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
[Display(Name = "Last Modified")]
public DateTime LastModified { get; set; }
[Display(Name = "Created By")]
public ApplicationUser Creator { get; set; }
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime Created { get; set; }
}
This works good, but I have to set these fields in every action in my controllers. How can I set these fields every time an item in my database is updated or edited? I am aware that I could override Add
in my DbContext
, but I have no idea how to get the ApplicationUser
from the HttpContext.Current.User.Identity
in my DbContext
. I have tried:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> {
private readonly UserManager<ApplicationUser> userManager;
private readonly HttpContext httpContext;
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, UserManager<ApplicationUser> userManager, IHttpContextAccessor contextAccessor)
: base(options)
{
this.contextAccessor = contextAccessor;
this.httpContext = contextAccessor.HttpContext;
this.userManager = userManager;
}
public override EntityEntry<TEntity> Add<TEntity>(TEntity entity)
{
DatabaseEntity dbEntity = (entity as DatabaseEntity);
if (dbEntity != null)
{
dbEntity.Created = DateTime.Now;
dbEntity.Creator = await userManager.GetUserAsync(httpContext.User);
}
return base.Add(entity);
}
}
but this gives error because userManager.GetUserAsync(httpContext.User);
requires an await
and public override EntityEntry<TEntity> Add<TEntity>(TEntity entity)
is not async.
回答1:
For getting current user, you should not use UserManager<ApplicationUser>
. With commenting dbEntity.Creator = await userManager.GetUserAsync(httpContext.User);
, you will get error A circular dependency was detected for the service of type 'CoreDb.Data.ApplicationDbContext'. due to that you accessing UserManager<ApplicationUser>
in ApplicationDbContext
.
I suggest you try get the current user by querying DbSet<ApplicationUser>
with current user name.
Here is a simple code:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
private readonly HttpContext httpContext;
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IHttpContextAccessor contextAccessor)
: base(options)
{
this.httpContext = contextAccessor.HttpContext;
}
public DbSet<ApplicationUser> ApplicationUser { get; set; }
public override EntityEntry<TEntity> Add<TEntity>(TEntity entity)
{
DatabaseEntity dbEntity = (entity as DatabaseEntity);
var userName = httpContext.User.Identity.Name;
if (dbEntity != null)
{
dbEntity.Created = DateTime.Now;
dbEntity.Creator = userName == null ? null : ApplicationUser.Where(user => user.UserName == userName).FirstOrDefault();
}
return base.Add(entity);
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
来源:https://stackoverflow.com/questions/49142880/mvc-tracking-fields-such-as-author-and-editor-created-by-and-modified-by