Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AspNetCore unable to resolve service

I'm adding Microsoft.AspNetCore.Identity to a project, and I get

InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.SignInManager'1[Web.Security.Entities.IUser'1[System.Int32]]' while attempting to activate 'Web.Security.Services.SecurityService'2[Web.Security.Entities.IUser'1[System.Int32],System.Int32]'.

Exception is copypasted from postman, it encoded some symbols. Here's my Startup.cs:

public class Startup
{
    ServiceProvider serviceProvider;
    IConfigurationRoot configurationRoot;
    public IConfiguration Configuration { get; }
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;

        configurationRoot = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", optional: false)
            .AddIniFile("3CXPhoneSystem.ini")
            .Build();
    }
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        serviceProvider = services
                  .AddLogging((builder) => builder.SetMinimumLevel(LogLevel.Trace))            
           .AddSingleton<ISecurityService, SecurityService<IUser<int>, int>>()
                 .AddSingleton<ITaskService, TaskService>()
                 .AddTransient<IEmailSender, EmailSender>()
                 .AddSingleton<ITranslation, Translation>()
           .BuildServiceProvider();
        services.AddDbContext<SecurityDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("dataContext")));

        services.AddIdentity<Web.Security.Entities.User<int>, IdentityRole>()
        .AddEntityFrameworkStores<SecurityDbContext>()
        .AddDefaultTokenProviders();

        services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
        {
            builder
            .AllowAnyMethod()
            .AllowAnyHeader()
            .WithOrigins("http://localhost:52170");
        }));
        services.AddMvc();

        services.Configure<IdentityOptions>(options =>
        {
            // Password settings
            options.Password.RequireDigit = true;
            options.Password.RequiredLength = 8;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireUppercase = true;
            options.Password.RequireLowercase = false;
            options.Password.RequiredUniqueChars = 6;

            // Lockout settings
            options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
            options.Lockout.MaxFailedAccessAttempts = 10;
            options.Lockout.AllowedForNewUsers = true;

            // User settings
            options.User.RequireUniqueEmail = true;
        });


    }



    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        app.UseDefaultFiles();
        app.UseStaticFiles();

        app.Use(async (context, next) =>
        {
            await next();

            if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value) && !context.Request.Path.Value.StartsWith("api"))
            {
                context.Response.Redirect("/");
            }
        });


        app.UseMvc(routes =>
        {
            routes.MapRoute(name: "DefaultApi", template: "api/{controller}/{action}/{id?}");
            routes.MapRoute("RouteToAngular", "{*url}", defaults: new { controller = "Route", action = "Index" });

        });

        app.UseAuthentication();

        app.UseCors("CorsPolicy");
    }

Here, SecurityService is a class that will handle registration/login/other identity related requests, it looks like this

public class SecurityService<TUser, TKey> : ISecurityService where TUser : class, IUser<TKey>
{
    SignInManager<TUser> signInManager;
    IConfiguration configuration;
    private readonly IHttpContextAccessor httpContextAccessor;
    UserManager<TUser> userManager;
    IEmailSender emailSender;
    IUrlHelper urlHelper;
    ISession session;
    ILogger<SecurityService<TUser, TKey>> logger;
    ITranslation translation; 

    public SecurityService(
        SignInManager<TUser> signInManager,
        UserManager<TUser> userManager,
        IConfiguration configuration,
        IHttpContextAccessor httpContextAccessor,
        IEmailSender emailSender,
        IUrlHelper urlHelper,
        ISession session,
        ILogger<SecurityService<TUser, TKey>> logger,
        ITranslation translation)
    {
        this.signInManager = signInManager;
        this.userManager = userManager;
        this.configuration = configuration;
        this.httpContextAccessor = httpContextAccessor;
        this.urlHelper = urlHelper;
        this.session = session;
        this.logger = logger;
        this.translation = translation;
        this.emailSender = emailSender;
    }

IUser.cs:

public interface IUser<TKey>
{
    TKey Id { get; set; }
    string UserName { get; set; }
    string Email { get; set; }
    bool EmailConfirmed { get; set; }
}
like image 619
Jamil Avatar asked Jul 03 '18 10:07

Jamil


People also ask

Which exception may be caused by missing service registrations?

Open generic types aren't checked The service provider validation completely skips over the open generic registration, so it never detects the missing DataService dependency. The app starts up without errors, and will throw a runtime exception if you try to request a ForecastService<T> .

What is ASP.NET Core session?

Session state. Session state is an ASP.NET Core scenario for storage of user data while the user browses a web app. Session state uses a store maintained by the app to persist data across requests from a client. The session data is backed by a cache and considered ephemeral data.

What is IServiceCollection in .NET Core?

IServiceCollection is the collection of the service descriptors. We can register our services in this collection with different lifestyles (Transient, scoped, singleton) IServiceProvider is the simple built-in container that is included in ASP.NET Core that supports constructor injection by default.

How do I update my ASP.NET Core app?

To check, right click on dependencies and choose manage NuGet Packages. And in the update tab, you'll see a list of packages which are available for updates. Like in this case, there is an update available for the “Microsoft. AspNetCore.


1 Answers

You need to use the IdentityBuilder extension method AddSignInManager explicitly.

services.AddIdentity<Web.Security.Entities.User<int>, IdentityRole>()
    .AddEntityFrameworkStores<SecurityDbContext>()
    // Replace ApplicationUser with your concrete user class
    .AddSignInManager<SignInManager<ApplicationUser>>() 
    .AddDefaultTokenProviders();

If you need access to it in your security service then you can inject it:

public class SecurityService<TUser, TKey> ...
{
    public SecurityService(SignInManager<ApplicationUser> signInManager)
    {
        this.signInManager = signInManager;
    }
}
like image 85
Chris Pickford Avatar answered Oct 11 '22 01:10

Chris Pickford