Unable to resolve service for type IEmailSender while attempting to activate RegisterModel

Viewed 22825

I'm using Identity and I have a problem that I make a new example project and with individual authentication and scaffold identity InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UI.Services.IEmailSender' while attempting to activate 'MASQ.Areas.Identity.Pages.Account.RegisterModel'.

6 Answers

I am using ASP.NET Core 3.0 and had similar issue. I added the following .AddDefaultUI() to my Startup.cs & it worked.

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));
            services.AddIdentity<IdentityUser, IdentityRole>()
                .AddDefaultTokenProviders()
                .AddDefaultUI()
                .AddEntityFrameworkStores<ApplicationDbContext>();

            services.AddControllersWithViews();
            services.AddRazorPages().AddRazorRuntimeCompilation();
        }

There're two ways to do that :

  1. remove the services.AddDefaultTokenProviders() in the ConfigurureServices() to disable two-factor authentication (2FA) :
    // file: `Startup.cs` :
    services.AddDefaultIdentity<IdentityUser>()
        .AddEntityFrameworkStores<ApplicationDbContext>();
        ///.AddDefaultTokenProviders(); /// remove this line
    
  2. Add your own IEmailSender and ISmsSender implementation to DI contianer if you would like to enable 2FA

    // file: `Startup.cs`
    
    services.AddTransient<IEmailSender,YourEmailSender>();
    services.AddTransient<IEmailSender,YourSmsSender>();
    

Edit:

Both should work.

Both should work for ASP.NET Core 2.1. However, as of ASP.NET Core 3.0, the first approach doesn't work any more.

Add Default UI in the configuration service:

services.AddIdentity<IdentityUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders()
    .AddDefaultUI();

For ASP.NET Core 5.0 you can use the following code, instead of calling AddIdentity

services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<AppDbContext>()
            .AddDefaultTokenProviders();
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });
        services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
        services.AddIdentity<ApplicationUser, ApplicationRole>(
           option => {
               option.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
               option.Lockout.MaxFailedAccessAttempts = 5;
               option.Lockout.AllowedForNewUsers = false;
           })
          .AddEntityFrameworkStores<ApplicationDbContext>()
          .AddDefaultTokenProviders();

        //services.AddDbContext<ApplicationDbContext>(options =>
        //    options.UseSqlServer(
        //        Configuration.GetConnectionString("DefaultConnection")));
        //services.AddIdentity<ApplicationUser, IdentityRole>()
        //    .AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();

        services.AddTransient<Areas.Identity.Services.IEmailSender, AuthMessageSender>();

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    // 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.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();

        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

maybe it's my time to be usefull. Since approach with green checkmark doesn't work in core 3.0 I have an idea. Basicaly you need to disable IEmailSender service. I think that not the best aproach, but if you dont need IEmailSender and you just want to quickly setup user functionality you can go to Register.cshtml.cs and comment out (or delete) private readonly IEmailSender _emailSender; and everywhere it is used in this controller. Hope it helps.

Related