Ho due progetti nella mia soluzione, UI come progetto mvc e classe per il codice del modello entitiy prima. Ho molte entità nel mio modello, ma ora ho bisogno di estenderle con nuovi campi di controllo in cui ho bisogno di salvare chi ha cambiato entità. Ho aggiunto una nuova interfaccia
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; }
}
e prova ad estendere SaveChanges in questo modo
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;
}
}
ma come posso ottenere userName qui? Non posso usare alcun getCser httpContex perché questo è un progetto di classe. Qualche idea?
questo è il mio contesto
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDbContext
quindi ho pensato di estendere ApplicationUser da un altro campo come LogedUserName e riempirlo quando l'utente sta effettuando l'accesso, ma come ottengo questo campo nel mio metodo SaveChanges?
Se si è certi che questa libreria di classi sarà sempre utilizzata nella pipeline ASP.NET, è possibile accedere a HttpContext
. Hai bisogno di un riferimento a System.Web
nella tua libreria di classi e poi:
using System.Web;
[...]
public void SaveChanges()
{
var username = HttpContext.Current.User.Identity.Name;
}
In questo caso HttpContext
è una classe statica, non una proprietà.
Naturalmente questo fallirebbe male se questa classe viene mai usata al di fuori della pipeline ASP.NET (ad esempio nell'applicazione WPF, nell'app console, ecc.). Inoltre non sembra pulito per farlo in questo modo. Ma è probabilmente il modo più veloce che richiede il minimo cambiamento di codice esistente.
Un altro modo sarebbe passare il nome utente o l'intera identità alla classe responsabile del salvataggio delle modifiche o direttamente al metodo SaveChanges
.
Un'implementazione potrebbe assomigliare a questa:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDbContext
{
private IPrincipal _currentUser;
public ApplicationDbContext(IPrincipal currentUser)
{
_currentUser = currentUser;
}
}
e poi in Controller (se si utilizza il contesto direttamente nei controller MVC):
using(var db = new ApplicationDbContext(User))
{
[...]
}
dove User
è la proprietà del controller che mantiene l'utente corrente.