asp.net - UserManager.GetUserAsync 不跟踪更改?
问题描述
我正在使用以下函数来检查想要访问某些数据库记录的人是否是该记录的所有者:
public class AccessGuard
{
public async Task<bool> IsOwnerOrHaveRightsAsync(UserManager<ApplicationUser> userManager, ApplicationUser claimant, ClaimsPrincipal User)
{
ApplicationUser fullUser = await userManager.GetUserAsync(User);
if (claimant.Id == fullUser.Id)
{
return true;
}
return false;
}
}
它有效,但正如我所注意到的:ApplicationUser
现在已添加到 ChangeTracker。这意味着我不能userManager.GetUserAsync
稍后在代码中调用,因为我收到此错误:
无法跟踪实体类型“ApplicationUser”的实例,因为已经在跟踪具有相同键值 {'Id'} 的另一个实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。
我通常.AsNoTracking()
在访问数据库记录时使用,但在 userManager 中没有类似的东西。你会如何解决这个问题?
我在 MVC Controller 方法中使用它,如下所示:
if (!await new AccessGuard().IsOwnerOrHaveRightsAsync(_userManager, Post.Author, User))
{
return Unauthorized();
}
解决方案
你不能使用.AsNoTracking()
with await userManager.GetUserAsync(User);
。或者,您可以执行以下操作:
public class AccessGuard
{
private readonly ApplicationDbContext _context;
private readonly IHttpContextAccessor _httpContextAccessor;
public AccessGuard(ApplicationDbContext context, IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
_context = context;
}
public async Task<bool> IsOwnerOrHaveRightsAsync(UserManager<ApplicationUser> userManager, ApplicationUser claimant, ClaimsPrincipal User)
{
var loggedInUserId = _httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
ApplicationUser fullUser = _context.ApplicationUsers.AsNoTracking()
.FirstOrDefaultAsync(au => au.Id == loggedInUserId);
if (claimant.Id == fullUser.Id)
{
return true;
}
return false;
}
}
然后你应该IHttpContextAccessor
在Startup
类中注册如下:
public void ConfigureServices(IServiceCollection services)
{
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// Or you can also register as follows
services.AddHttpContextAccessor();
}
AccessGuard
然后在你的 MVC 控制器方法中访问服务,首先AccessGuard
在 Startup 中注册如下:
services.AddScoped<AccessGuard>();
然后在您的控制器方法中:
public IActionResult Index()
{
AccessGuard accessGuardService = (AccessGuard) HttpContext.RequestServices.GetService(typeof(AccessGuard));
// Now call `accessGuardService` service method here
return View();
}
您还可以获得AccessGuard
以下服务:
AccessGuard accessGuardService = HttpContext.RequestServices.GetService<AccessGuard>();
它需要命名空间using Microsoft.Extensions.DependencyInjection;
推荐阅读
- maven - Maven 编译器:Xlint 和 showWarnings 之间的区别
- javascript - 为什么我无法获得选择选项 html 的值?
- java - 使用 pom.xml 将第三方库部署到工件
- javascript - 如何从反应应用程序的公共文件夹中导入文件?
- python - 如何从 model_utils 三重选择中获取密钥?
- list - Lisp 程序为每个增量创建一个子列表
- ruby - 序列化哈希数组
- javascript - 当我在聚合物 2 中输入我的电子邮件时,我的登录密码不会自动完成
- php - 内联键盘电报机器人 [PHP]
- excel - 将公式从活动单元格拖到右侧,其中行是可变的,但列是设置的