注册模板用户的用户管理器时的服务提供程序例外

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

我正在学习ASP .NET Core,今天我偶然发现了一些东西。我有User类继承IdentityUser并添加一些自定义字段,如名字,姓氏等...

User类进一步扩展到其他类型的用户,最多只添加一个或两个额外的字段。我决定采用这条路线,因为没有必要在4个地方重复相同的代码。

我已经定义了一个UserRepository,它实现了一个接口IUserRepository<TEntity> where TEntity : User。每当我尝试访问Index时,我都会遇到如下异常:

InvalidOperationException: No service for type 'Microsoft.AspNetCore.Identity.UserManager`1[HM.models.users.Medic]' has been registered.
Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<T>(IServiceProvider provider)
HM.repositories.UserRepository<TEntity>..ctor(ApplicationDbContext context, IServiceProvider serviceProvider, string role) in UserRepository.cs
+
            _userManager = serviceProvider.GetRequiredService<UserManager<TEntity>>();
HM.repositories.MedicRepository..ctor(ApplicationDbContext context, IServiceProvider serviceProvider) in MedicRepository.cs
+
        public MedicRepository(ApplicationDbContext context, IServiceProvider serviceProvider) : base(context, serviceProvider, _role) { }
HM.persistence.UnitOfWork..ctor(ApplicationDbContext context, IServiceProvider _serviceProvider) in UnitOfWork.cs
+
            Medics = new MedicRepository(_context, _serviceProvider);
app.Controllers.MedicController.Index() in MedicController.cs
+
            using (var unitOfWork = new UnitOfWork(_context, _serviceProvider))
Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

这些是一些代码片段:

MedicController

 // GET: Medic
   public async Task<IActionResult> Index()
    {
        using (var unitOfWork = new UnitOfWork(_context,_serviceProvider))
        {
            return View(await unitOfWork.Medics.GetAll());
        }
    }

UserRepositoryIUserRepository

   public interface IUserRepository<TEntity> where TEntity : User
    {
        Task Add(TEntity user, string password);
        Task Remove(TEntity user);
        Task Update(TEntity user);
        Task<IEnumerable<TEntity>> GetAll();
        Task<TEntity> GetById(string id);
        Task<bool> Any(Func<TEntity, bool> predicate);
    }

    public class UserRepository<TEntity> : IUserRepository<TEntity> where TEntity : User
    {
        private readonly string _role;
        private readonly UserManager<TEntity> _userManager;

        public UserRepository(ApplicationDbContext context, IServiceProvider serviceProvider, string role)
        {
            _role = role;
            _userManager = serviceProvider.GetRequiredService<UserManager<TEntity>>();
        }


        public async Task<IEnumerable<TEntity>> GetAll()
        {
            return await _userManager.GetUsersInRoleAsync(_role);
        }
    }

最后,医生:

[Table("Medic")]
public class Medic : User
{
    [DisplayName("Departments")]
    public ICollection<MedicDepartment> departments { get; set; }

    [DisplayName("Diagnostics")]
    public ICollection<MedicDiagnostic> diagnostics { get; set; }

    [PersonalData]
    [DisplayName("Rank")]
    [StringLength(30, MinimumLength = 3, ErrorMessage = "The rank name must be between 3 and 30 characters long!")]
    public string rank { get; set; }
}

我调试了应用程序:它将在_userManager = serviceProvider.GetRequiredService<UserManager<TEntity>>();中的UserRepository抛出此异常。我不明白为什么这个hapens,因为我已经明确说明where TEntity : User

谢谢!附:我删除了一些代码和一些方法,使这篇文章更加可更新。 P.S.S:MedicRepository类扩展UserRepository并调用base并且暂时包含其他内容。 UnitOfWork包含所有应用程序存储库,并在其构造函数中的每一个上调用new。 P.S.S.S.我想为此存储库使用模板,以避免在控制器内部进行转换。它曾用于返回“用户”相关数据。

asp.net-mvc
1个回答
1
投票

我想到了。仅为UserManager<User>注册服务是不够的,但我还必须为继承UserManager的每种类型的用户注册User

首先,我将这些线添加到Startup.cs内的ConfigureServices。这使用IdentityCore而不是Identity

        services.AddIdentityCore<Medic>()                       //add the derived user type from custom user
            .AddRoles<IdentityRole>()
            .AddClaimsPrincipalFactory<UserClaimsPrincipalFactory<Medic, IdentityRole>>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders()
            .AddDefaultUI();

其次,不要忘记添加经理。与以前相同,在同一文件和方法中,添加:

   services.AddScoped<UserManager<User>, UserManager<User>>();     //the user manager for the base type of User
   services.AddScoped<UserManager<Medic>, UserManager<Medic>>();   //the user manager for Medics

希望能帮助到你!

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