AspNetCore 2.1 IdentityDbContext: как получить текущее имя пользователя - PullRequest
1 голос
/ 28 июня 2019

В проекте, над которым я сейчас работаю, мне нужно проверить изменения во многих таблицах базы данных. Для этого я рассматриваю возможность работы с nuget Z.EntityFramework.Plus.Audit.EFCore . Я экспериментировал, и это, кажется, в основном соответствует моим потребностям. Я следил за документами здесь .

Можно сохранить записи аудита в моем контроллере следующим образом:

public myFunction(){
   //... 
   var audit = new Audit();
   _context.SaveChanges(audit); 
}

Но если я сделаю это таким образом, это нарушит принцип СУХОЙ. Есть способ переопределить функции SaveChanges () и SaveChagesAsync (), и он творит чудеса. Такая вещь делается так:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
        {
            AuditManager.DefaultConfiguration.AutoSavePreAction = (context, audit) =>
               // ADD "Where(x => x.AuditEntryID == 0)" to allow multiple SaveChanges with same Audit
               (context as ApplicationDbContext).AuditEntries.AddRange(audit.Entries);
        }


        public override int SaveChanges()
        {
            var audit = new Audit { }; //Problem would be here
            audit.PreSaveChanges(this);
            var rowAffecteds = base.SaveChanges();
            audit.PostSaveChanges();

            if (audit.Configuration.AutoSavePreAction != null)
            {
                audit.Configuration.AutoSavePreAction(this, audit);
                base.SaveChanges();
            }

            return rowAffecteds;
        }

        public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
        {
            var audit = new Audit { }; //Problem would be here
            audit.PreSaveChanges(this);
            var rowAffecteds = await base.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            audit.PostSaveChanges();

            if (audit.Configuration.AutoSavePreAction != null)
            {
                audit.Configuration.AutoSavePreAction(this, audit);
                await base.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            }

            return rowAffecteds;
        }

//... DbContext Code
        }

Теперь это лучший вариант, очень СУХОЙ и более экологичный. Проблема в том, как получить текущее имя пользователя, чтобы я мог сделать что-то вроде

var audit = new Audit { CreatedBy = "my_current_username"};

В контроллере вы можете использовать инструкцию

var username = this.User.Identity.Name;

но это не доступно в IdentityDbContext. Я попробовал ввести UserManager, но у него не было функции, которая могла бы работать.

ТЛ; др; Как получить текущее имя пользователя в IdentityDbContext, когда я использую токены JWT?

Ответы [ 2 ]

2 голосов
/ 28 июня 2019

В ConfigureServices:

services.AddHttpContextAccessor();

services.AddDbContext<FooContext>((provider, options) =>
    options.UseSqlServer(Configuration.GetConnectionString("Foo"))
           .UseInternalServiceProvider(provider);

В FooContext.SaveChanges / FooContext.SaveChangesAsync:

var httpContextAccessor = this.GetService<IHttpContextAccesor>();
var userName = httpContextAccessor.HttpContext?.User.Identity.Name;
if (userName != null)
{
    // You've got the username. Do something with it.
}
0 голосов
/ 28 июня 2019

Вы можете добавить службу IHTTPContextAccessor, а затем использовать ее для получения текущего имени пользователя. Однако эта служба НЕ является поточно-ориентированной Кроме того, это означает, что вы не можете использовать DBContext вне области действия веб-приложения AFAIK.

Подробнее здесь: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-2.2

...