web-dev-qa-db-fra.com

Comment obtenir des informations utilisateur dans DbContext à l'aide de Net Core

J'essaie de développer une bibliothèque de classes dans laquelle je souhaite implémenter DbContext personnalisé. Dans la méthode SaveChanges de DbContext, j'ai besoin d'obtenir les informations de l'utilisateur actuel (service, nom d'utilisateur, etc.) à des fins d'audit. Une partie du code DbContext est ci-dessous:

public override int SaveChanges()
{
    // find all changed entities which is ICreateAuditedEntity 
    var addedAuditedEntities = ChangeTracker.Entries<ICreateAuditedEntity>()
           .Where(p => p.State == EntityState.Added)
           .Select(p => p.Entity);

    var now = DateTime.Now;

    foreach (var added in addedAuditedEntities)
    {
        added.CreatedAt = now;
        added.CreatedBy = ?;
        added.CreatedByDepartment = ?
    }
    return base.SaveChanges();
}

Deux options viennent à l'esprit:

  • En utilisant HttpContext.Items pour conserver les informations utilisateur, injecter IHttpContextAccessor et obtenir des informations à partir de HttpContext.Items (Dans ce cas DbContext dépend HttpContext, est-ce correct?)
  • Utilisation de l'objet ThreadStatic au lieu de HttpContext.Items et obtenir des informations de l'objet (j'ai lu certains articles que ThreadStatic n'est pas sûr)

Question: Quel est le mieux adapté à mon cas? Y a-t-il une autre façon de suggérer?

17
adem caglin

J'ai implémenté une approche similaire à celle décrite dans cet article de blog et implique essentiellement la création d'un service qui utilisera l'injection de dépendance pour injecter le HttpContext (et les informations utilisateur sous-jacentes) dans un particulier contexte ou comme vous préférez l’utiliser.

Une implémentation très basique pourrait ressembler à ceci:

public class UserResolverService  
{
    private readonly IHttpContextAccessor _context;
    public UserResolverService(IHttpContextAccessor context)
    {
        _context = context;
    }

    public string GetUser()
    {
       return _context.HttpContext.User?.Identity?.Name;
    }
}

Vous auriez juste besoin d'injecter cela dans le pipeline au sein de la méthode ConfigureServices dans votre Startup.cs fichier :

services.AddTransient<UserResolverService>();

Et enfin, accédez-y simplement dans le constructeur de votre DbContext spécifié:

public partial class ExampleContext : IExampleContext
{
    private YourContext _context;
    private string _user;
    public ExampleContext(YourContext context, UserResolverService userService)
    {
        _context = context;
        _user = userService.GetUser();
    }
}

Vous devriez alors pouvoir utiliser _user pour référencer l'utilisateur actuel dans votre contexte. Cela peut facilement être étendu pour stocker/accéder à tout contenu disponible dans la demande actuelle.

37
Rion Williams