UserManager.GetUserAsync没有跟踪的变化?

问题描述 投票:0回答:1

我使用下面的函数来检查要访问某些数据库记录的人是否是该记录的拥有者:

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控制器方法如下使用它:

if (!await new AccessGuard().IsOwnerOrHaveRightsAsync(_userManager, Post.Author, User))
{
     return Unauthorized();
}
asp.net entity-framework asp.net-core entity-framework-core
1个回答
1
投票

你不能.AsNoTracking()使用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;
   }
}

那么你应该在IHttpContextAccessorStartup登记如下:

public void ConfigureServices(IServiceCollection services)
{
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    // Or you can also register as follows

    services.AddHttpContextAccessor();
}

然后访问AccessGuard服务在你的MVC控制器的方法,首先在启动注册AccessGuard如下:

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;

© www.soinside.com 2019 - 2024. All rights reserved.