C# ASP.NET Core 2.2在DbContext中获取用户ID
我对ASP.NET核心相当陌生。 我想创建ASP.NET Core 2.2 WebAPI,具有实体框架核心和ASP.NET标识。 另外,我想使用JWT来保护使用令牌访问WebAPI的安全 我已经成功地将用户插入数据库,并从我的API获取令牌,令牌身份验证正在工作 但是,我还想软删除数据库记录,并跟踪谁删除/更新/添加了记录。 这是国家/地区的测试表,其中字段仅为C# ASP.NET Core 2.2在DbContext中获取用户ID,c#,entity-framework,asp.net-core,entity-framework-core,asp.net-identity,C#,Entity Framework,Asp.net Core,Entity Framework Core,Asp.net Identity,我对ASP.NET核心相当陌生。 我想创建ASP.NET Core 2.2 WebAPI,具有实体框架核心和ASP.NET标识。 另外,我想使用JWT来保护使用令牌访问WebAPI的安全 我已经成功地将用户插入数据库,并从我的API获取令牌,令牌身份验证正在工作 但是,我还想软删除数据库记录,并跟踪谁删除/更新/添加了记录。 这是国家/地区的测试表,其中字段仅为Title和Description 到目前为止,我已经彻底颠覆了互联网,但没有任何帮助:( 我尝试过的最后一件事是(userId是nul
Title
和Description
到目前为止,我已经彻底颠覆了互联网,但没有任何帮助:(
我尝试过的最后一件事是(userId是null
):
- 在startup.cs中:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton();
- 在我的AppDbContext.cs中
public class AppDbContext : IdentityDbContext<AppUser>{ public AppDbContext(DbContextOptions options) : base(options) { } public DbSet<AppUser> AppUsers { get; set; } public DbSet<Country> Countries { get; set; } // just for testing protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); // TODO - IGNORE THIS //builder.Entity<AppUser>().Property<bool>("IsDeleted"); //builder.Entity<AppUser>().HasQueryFilter(m => EF.Property<bool>(m, "IsDeleted") == false); } public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)) { CheckBeforeSaving(); return (await base.SaveChangesAsync(true, cancellationToken).ConfigureAwait(false)); } private void CheckBeforeSaving() { var httpContextAccessor = this.GetService<IHttpContextAccessor>(); var userId = httpContextAccessor?.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier); foreach (var entry in ChangeTracker.Entries()) { switch (entry.State) { case EntityState.Detached: break; case EntityState.Unchanged: break; case EntityState.Deleted: entry.State = EntityState.Modified; entry.CurrentValues["IsDeleted"] = true; entry.CurrentValues["DeletedBy"] = userId; entry.CurrentValues["Deleted"] = DateTime.Now; break; case EntityState.Modified: entry.CurrentValues["UpdatedBy"] = userId; entry.CurrentValues["Updated"] = DateTime.Now; break; case EntityState.Added: entry.CurrentValues["IsDeleted"] = false; entry.CurrentValues["CreatedBy"] = userId; entry.CurrentValues["Created"] = DateTime.Now; entry.CurrentValues["Description"] = userId; break; default: break; } } }}}
公共类AppDbContext:IdentityDbContext{ 公共AppDbContext(DbContextOptions选项):基本(选项) { } 公共DbSet AppUsers{get;set;} 公共DbSet Countries{get;set;}//仅用于测试 模型创建时受保护的覆盖无效(ModelBuilder) { 基于模型创建(生成器); //待办事项-忽略此项 //builder.Entity().Property(“IsDeleted”); //builder.Entity().HasQueryFilter(m=>EF.Property(m,“IsDeleted”)==false); } 公共覆盖异步任务saveChangesSync(CancellationToken CancellationToken=default(CancellationToken)) { 保存前检查(); return(wait base.savechangessync(true,cancellationToken.configurewait(false)); } 保存之前的私有无效检查() { var httpContextAccessor=this.GetService(); var userId=httpContextAccessor?.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier); foreach(ChangeTracker.Entries()中的var条目) { 开关(进入状态) { 案例实体状态。已分离: 打破 案例实体状态。未更改: 打破 案例实体状态。已删除: entry.State=EntityState.Modified; entry.CurrentValues[“IsDeleted”]=true; entry.CurrentValues[“DeletedBy”]=userId; entry.CurrentValues[“Deleted”]=DateTime.Now; 打破 案例实体状态。已修改: entry.CurrentValues[“UpdatedBy”]=userId; entry.CurrentValues[“Updated”]=DateTime.Now; 打破 案例实体状态。添加: entry.CurrentValues[“IsDeleted”]=false; entry.CurrentValues[“CreatedBy”]=userId; entry.CurrentValues[“Created”]=DateTime.Now; entry.CurrentValues[“Description”]=userId; 打破 违约: 打破 } } }}}
- 以下是我在.net core 2.2中获取用户id的方法
首先,您需要在Startup.cs中注册
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
下面是我在.NETCore2.2中获取用户id的方法 首先,您需要在Startup.cs中注册
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
尝试将
IHttpContextAccessor
直接注入ApplicationDbContext
:
public class ApplicationDbContext : IdentityDbContext<AppUser>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IHttpContextAccessor httpContextAccessor)
: base(options)
{
_httpContextAccessor= httpContextAccessor;
}
//other methods
private void CheckBeforeSaving()
{
var userId = _httpContextAccessor?.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
//...
}
}
public类ApplicationDbContext:IdentityDbContext
{
专用只读IHttpContextAccessor\u httpContextAccessor;
公共应用程序DBContext(DbContextOptions选项,IHttpContextAccessor httpContextAccessor)
:基本(选项)
{
_httpContextAccessor=httpContextAccessor;
}
//其他方法
保存之前的私有无效检查()
{
var userId=\u httpContextAccessor?.HttpContext.User.FindFirstValue(ClaimTypes.nameignifier);
//...
}
}
尝试将IHttpContextAccessor
直接注入ApplicationDbContext
:
public class ApplicationDbContext : IdentityDbContext<AppUser>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IHttpContextAccessor httpContextAccessor)
: base(options)
{
_httpContextAccessor= httpContextAccessor;
}
//other methods
private void CheckBeforeSaving()
{
var userId = _httpContextAccessor?.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
//...
}
}
public类ApplicationDbContext:IdentityDbContext
{
专用只读IHttpContextAccessor\u httpContextAccessor;
公共应用程序DBContext(DbContextOptions选项,IHttpContextAccessor httpContextAccessor)
:基本(选项)
{
_httpContextAccessor=httpContextAccessor;
}
//其他方法
保存之前的私有无效检查()
{
var userId=\u httpContextAccessor?.HttpContext.User.FindFirstValue(ClaimTypes.nameignifier);
//...
}
}
专用异步任务GetUserDetailsSansyc()
{
返回wait userManager.GetUserAnsync(HttpContext.User);
}
var user=await GetUserDetailsAnsyc();
Console.WriteLine(user.Id.ToString());
专用异步任务GetUserDetailsSansyc()
{
返回wait userManager.GetUserAnsync(HttpContext.User);
}
var user=await GetUserDetailsAnsyc();
Console.WriteLine(user.Id.ToString());
我不理解你的问题。如果你有一个usertable,appuser,那么检索id应该不会比其他id更困难。如果你有一个用户登录,或者有一个方法的访问权限,那么你就有信息来查找他并获取id。然后你可以有另一个表用于登录,这样当他执行操作时您可以将其与他的id和他的操作描述一起保存到日志中。但可能我在这里遗漏了一些内容,因为我不熟悉像您这样使用httpcontextaccessor。@Johan我可以通过使用ClaimSidentyid=identity.Claims.Single(c=>c.Type==“id”)在控制器中获取用户id.Value
但我无法将其放在appit的AppDbContext部分中。这很有趣。但我不明白您为什么要这样做。您可以通过在执行这些操作时将它们记录到另一个表中来跟踪所有这些内容。例如:if(_context.Entry(objectToDelete).State==EntityState.Detached){dbSet.Attach(objectToDelete);}dbSet.Remove(objectToDelete);然后创建一个表来记录此操作:var logg=new logg{userId=xxx,info=“username deleted country”,date=xxx等