Nie można rozpoznać usługi typu „Microsoft.AspNetCore.Identity.UserManager” podczas próby aktywowania „AuthController”

97

Otrzymuję ten błąd w kontrolerze logowania.

InvalidOperationException: nie można rozpoznać usługi typu „Microsoft.AspNetCore.Identity.UserManager” 1 [Automobile.Models.Account] ”podczas próby aktywacji„ Automobile.Server.Controllers.AuthController ”.

oto konstruktor Auth Controller:

private SignInManager<Automobile.Models.Account> _signManager;
    private UserManager<Automobile.Models.Account> _userManager;

    public AuthController(UserManager<Models.Account> userManager,
                          SignInManager<Automobile.Models.Account> signManager)
    {
        this._userManager = userManager;
        this._signManager = signManager;
    }

a oto ConfigureServices w startup.cs:

public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);
        services.Configure<AppConfig>(Configuration.GetSection("AppSettings"));

        //var provider = HttpContext.ApplicationServices;
        //var someService = provider.GetService(typeof(ISomeService));


        services.AddDbContext<Providers.Database.EFProvider.DataContext>(options => options
            .UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                 b => b.MigrationsAssembly("Automobile.Server")
            ));


        services.AddIdentity<IdentityUser, IdentityRole>(options =>
        {
            options.User.RequireUniqueEmail = false;
        })
        .AddEntityFrameworkStores<Providers.Database.EFProvider.DataContext>()
        .AddDefaultTokenProviders(); 
        //services.AddScoped<SignInManager<Automobile.Models.Account>, SignInManager<Automobile.Models.Account>>();
        //services.AddScoped<UserManager<Automobile.Models.Account>, UserManager<Automobile.Models.Account>>();

        services.AddMvc();
        App.Service = services.BuildServiceProvider();

        // Adds a default in-memory implementation of IDistributedCache.
        services.AddDistributedMemoryCache();

        services.AddSession(options =>
        {
            // Set a short timeout for easy testing.
            options.IdleTimeout = TimeSpan.FromSeconds(10);
            options.CookieHttpOnly = true;
        });

    }
OMID
źródło
23
Wydaje mi się, że rejestrujesz się IdentityUserjako podstawowa klasa użytkownika, ale potem używasz Automobile.Models.Account, która oczywiście nie jest nigdzie zarejestrowana przez ASP.NET Identity
Federico Dipuma
@FedericoDipuma Dziękuję bardzo :) Rozwiązany.
OMID
Jak to rozwiązałeś…?
Rafael
4
@Lobato w services.AddIdentity po prostu zastąp IdentityUser swoją klasą Identity User
OMID
1
@OMID, dlaczego nie opublikujesz swojego komentarza jako odpowiedzi, to mnie uratowało, ale po poważnym bólu głowy RnD ..
Null Pointer

Odpowiedzi:

92

Musisz użyć tego samego modelu danych użytkownika w SignInManager, UserManager i usługach.AddIdentity. Ten sam podmiot zabezpieczeń jest prawdziwy, jeśli używasz własnej niestandardowej klasy modelu roli aplikacji.

Więc zmień

services.AddIdentity<IdentityUser, IdentityRole>(options =>
    {
        options.User.RequireUniqueEmail = false;
    })
    .AddEntityFrameworkStores<Providers.Database.EFProvider.DataContext>()
    .AddDefaultTokenProviders();

do

services.AddIdentity<Automobile.Models.Account, IdentityRole>(options =>
    {
        options.User.RequireUniqueEmail = false;
    })
    .AddEntityFrameworkStores<Providers.Database.EFProvider.DataContext>()
    .AddDefaultTokenProviders();
HojjatK
źródło
2
Mam podobny problem, mam zdefiniowanego użytkownika i rolę klienta w metodzie AddIdentity i nadal otrzymuję ten sam błąd. Każdy pomysł, dlaczego? Mógłbym opublikować swój kod w osobnym wątku.
devC,
1
Właściwie rozwiązałem ten problem, ale teraz mam problem z tworzeniem połączenia DB. Opublikuję problem.
devC,
Wygląda na to, że parametry połączenia nie zostały poprawnie ustawione, sprawdź moją odpowiedź w swoim poście.
HojjatK
50

Żeby mieć jasność co do odpowiedzi:

Jeśli używasz klasy ApplicationUserw startup.cs:services.AddIdentity<ApplicationUser, IdentityRole>()

wtedy musisz użyć tej samej klasy w swoim kontrolerze podczas wstrzykiwania:

public AccountController(UserManager<ApplicationUser> userManager)

Jeśli używasz innej klasy, takiej jak:

public AccountController(UserManager<IdentityUser> userManager)

wtedy pojawi się ten błąd:

InvalidOperationException: nie można rozpoznać usługi dla typu „Microsoft.AspNetCore.Identity.UserManager” 1 [IdentityUser] ”

bo użyłeś ApplicationUserprzy starcie, nie IdentityUserwięc ten typ nie jest zarejestrowany w systemie wtrysku.

Greg Gum
źródło
6
Dotyczy to wszystkich odwołań, więc jeśli zaimplementujesz nową tożsamość Razor dla asp.net core 2,1 w celu zastąpienia starego systemu tożsamości, musisz zamienić ich automatyczną implementację rzeczy, takich jak SignInManager <IdentityUser>, na SignInManager <ApplicationUser> wszędzie tam, gdzie jest używana. To może być denerwujące. Musisz także zmienić trasę z normalnego / Konto / Zaloguj się do / Tożsamość / Konto / Login itp. Tylko kilka wskazówek, które pomogą;)
Johan Herstad
16

Jest to trochę niezwiązane z oryginalnym postem, ale ponieważ Google przenosi Cię tutaj ... jeśli otrzymujesz ten błąd i używasz:

services.AddIdentityCore<YourAppUser>()

Następnie musisz ręcznie zarejestrować rzeczy, które to AddIdentityrobią, które można znaleźć tutaj: https://github.com/aspnet/Identity/blob/feedcb5c53444f716ef5121d3add56e11c7b71e5/src/Identity/IdentityServiceCollectionExtensions.cs#L79

        services.AddHttpContextAccessor();
        // Identity services
        services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
        services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
        services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
        services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
        services.TryAddScoped<IRoleValidator<TRole>, RoleValidator<TRole>>();
        // No interface for the error describer so we can add errors without rev'ing the interface
        services.TryAddScoped<IdentityErrorDescriber>();
        services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
        services.TryAddScoped<ITwoFactorSecurityStampValidator, TwoFactorSecurityStampValidator<TUser>>();
        services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();
        services.TryAddScoped<UserManager<TUser>>();
        services.TryAddScoped<SignInManager<TUser>>();
        services.TryAddScoped<RoleManager<TRole>>();

Trzeba wymienić TUseri TRoleze swoimi implementacji tych, lub domyślnie IdentityUser,IdentityRole

Serj Sagan
źródło
Musiałem stworzyć niestandardowego SignInManager i to naprawiło, jeśli planujesz to zrobić, sprawdź github.com/dotnet/docs/issues/14828
perustaja
Początkowo zacząłem od tej drogi, ale tutaj znalazłem rozwiązanie ( stackoverflow.com/a/60752194/1146862 ) bardziej proste; Jedyna zmiana, jaką musiałem wprowadzić (po ponownym zamówieniu AddIdentityi AddJwtBearerpolegała na ustawieniu wszystkich trzech opcji pokazanych w przykładzie; używałem tylko DefaultAuthenticationScheme. Nadal otrzymuję plik cookie z powrotem przy logowaniu, ale [Authorize]teraz działa dla tokenów JWT bez określania AuthenticationSchema.
Aaron
Właśnie tego mi brakowało. Dodanie TryAddScoped<UserManager<TUser>>();i services.TryAddScoped<SignInManager<TUser>>();do mojego Startup.cs rozwiązało mój problem.
MorganR
4

nie zapomnij dodać menedżera ról w ConfigureServices

services.AddDefaultIdentity<IdentityUser>()
    .AddRoles<IdentityRole>() // <--------
    .AddDefaultUI(UIFramework.Bootstrap4)
    .AddEntityFrameworkStores<ApplicationDbContext>();
Ozzy
źródło
3

Możesz ustawić IdentityUser i IdentityRole w ConfigureServices wewnątrz klasy Startup indywidualnie, jak pokazano poniżej:

services.AddDefaultIdentity<IdentityUser>()
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

LUB

możesz skonfigurować bezpośrednio w AddIdentity:

services.AddIdentity<IdentityUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>();
Mahavirsinh Padhiyar
źródło
4
Mając tylko kod, OP i inni prawie nie dowiedzą się o problemie, rozważ edycję odpowiedzi i dodanie wyjaśnienia
Cleptus
0

Jeśli używasz „IdentityServer”, to IdentityServer uwierzytelnia użytkownika i autoryzuje klienta. Domyślnie IdentityServer nie dotyczy zarządzania użytkownikami. Ale istnieje wsparcie dla tożsamości asp.net

Więc musisz dodać:

services.AddIdentityServer()
    .AddAspNetIdentity<ApplicationUser>();
Amirhossein Yari
źródło
0

Musisz zaktualizować swoją klasę Statup.cs poniżej

services.AddIdentity <ApplicationUser, IdentityRole> () .AddEntityFrameworkStores ();

Tutaj: ApplicationUser to moja niestandardowa klasa modelu.

Gaurav Joshi
źródło