Entity Framework get user from contex in saveChang

2019-08-06 16:35发布

问题:

i have two projects in my solution, UI as mvc and class project for entitiy model code first. I have severall entities in my model but now I need to extend them by new audit fields where I need to save who changed entity. I added new interface

public interface IAuditable
{
    /// <summary>Gets or sets the name.</summary>
    /// <value>The name.</value>
    DateTime CreatedDate { get; set; }

    /// <summary>Gets or sets the name.</summary>
    /// <value>The name.</value>
    string CreatedBy { get; set; }

    /// <summary>Gets or sets the name.</summary>
    /// <value>The name.</value>
    DateTime UpdatedDate { get; set; }

    /// <summary>Gets or sets the name.</summary>
    /// <value>The name.</value>
    string UpdatedBy { get; set; }
}

and try to extend SaveChanges in this way

foreach (var auditableEntity in ChangeTracker.Entries<IAuditable>())
                {
                    if (auditableEntity.State == EntityState.Added ||
                        auditableEntity.State == EntityState.Modified)
                    {
                        // implementation may change based on the useage scenario, this
                        // sample is for forma authentication.
                        string currentUser = ; 

                        // modify updated date and updated by column for 
                        // adds of updates.
                        auditableEntity.Entity.UpdatedDate = DateTime.Now;
                        auditableEntity.Entity.UpdatedBy = 

                        // pupulate created date and created by columns for
                        // newly added record.
                        if (auditableEntity.State == EntityState.Added)
                        {
                            auditableEntity.Entity.CreatedDate = DateTime.Now;
                            auditableEntity.Entity.CreatedBy = currentUser;
                        }
                        else
                        {
                            auditableEntity.Property(p => p.CreatedDate).IsModified = false;
                            auditableEntity.Property(p => p.CreatedBy).IsModified = false;
                        }
                    }

but how do I get the userName here ? I can't use any httpContex getUser becuase this is class project. Any ideas?

this is my contex

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDbContext

so I thought to extend ApplicationUser by another field like LogedUserName, and fill it when user is loging, but how do I get this field in my SaveChanges method ?

回答1:

If you are sure that this class library will be always used in ASP.NET pipeline you actually can access HttpContext. You need a reference to System.Web in your class library and then:

using System.Web;
[...]
public void SaveChanges()
{
    var username = HttpContext.Current.User.Identity.Name;
}

In this case HttpContext is a static class, not a property.

Ofcourse this will fail badly if this class is ever used outside ASP.NET pipeline (for example in WPF application, console app etc). Also it doesn't seem clean to do it this way. But it's probably the fastest way which requires minimal existing code change.

Another way would be to pass either username or whole identity to either class responsible for saving changes or directly to SaveChanges method.

One implementation could look like this:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDbContext
{
    private IPrincipal _currentUser;
    public ApplicationDbContext(IPrincipal currentUser)
    {
        _currentUser = currentUser;
    }
}

and then in Controller (if you use context directly in MVC controllers):

using(var db = new ApplicationDbContext(User))
{
    [...]
}

where User is controller's property holding current user.