Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IServiceCollection does not contain a definition for AddDefaultIdentity

Any idea why am I getting this error?   Error Message --> "IServiceCollection does not contain a definition for AddDefaultIdentity"

public class Program
{
    public async static void Main(string[] args)
    {
        await Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder => {
           webBuilder.UseContentRoot(Directory.GetCurrentDirectory());
           webBuilder.UseKestrel();
           webBuilder.UseAzureAppServices();
           webBuilder.UseStartup<Startup>();
       })
      .Build()
      .RunAsync();
   }
}

public class Startup
{
    public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment)
    {
        Configuration = configuration;
        HostEnvironment = hostEnvironment;
    }

    public IConfiguration Configuration { get; }
    protected IApplicationBuilder ApplicationBuilder { get; private set; }
    public IHostEnvironment HostEnvironment { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        //           services.AddRazorPages();

        services.AddDefaultIdentity<ApplicationUser>()  // "ApplicationUser" is named incorrectly, it should be "IdentityUser" instead, as per Microsoft documentation.
            .AddRoles<IdentityRole<Guid>>()
            .AddEntityFrameworkStores<ApplicationContext, Guid>()  // FYI - AddEntityFrameworkStores() deal with role that derives from IdentityRole, as per documentation.
            //.AddDefaultUI()
            .AddDefaultTokenProviders();

        // [ Old version #1 - replacement ]
        services.ConfigureApplicationCookie(options =>
        {
            options.LoginPath = new PathString("/Home/Index");
            options.SlidingExpiration = true;
            options.ExpireTimeSpan = TimeSpan.FromMinutes(this.Configuration.GetValue<int?>("Authentication:SlidingExpirationTime").Value);
            options.AccessDeniedPath = new PathString("/Home/AccessDenied");
        });

        // [ Old version #2 - replacement ]
        services.Configure<IdentityOptions>(options =>
        {
            options.Password.RequireUppercase = false;
            options.Password.RequireLowercase = false;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireDigit = false;
            options.Password.RequiredLength = 7;
        });

        services.AddMvc();
        services.AddSession();

        //services.Configure<AuthorizationOptions>(options =>
        //{
        //});
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
           app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });

        // Config Exception.
        if (env.IsDevelopment())
            app.UseDeveloperExceptionPage();
        else
            app.UseExceptionHandler("/Home/ErrorPage.html");
        
        app.UseStaticFiles(); // Note, we are not authenticating for static files if this is before them
        app.UseSession();
        app.UseAuthentication();

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

public class ApplicationUser : IdentityUser<Guid>, IUser
{
}

public interface IUser
{
}

public class ApplicationContext : IdentityDbContext<ApplicationUser, IdentityRole<Guid>, Guid>
{
    public ApplicationContext(DbContextOptions<ApplicationContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
    }
}
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.DataProtection" Version="3.1.3" />
    <PackageReference Include="Microsoft.AspNetCore.DataProtection.AzureStorage" Version="1.0.2" />
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Xml" Version="1.1.3" />
    <PackageReference Include="Microsoft.AspNetCore.Session" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.3" />
    <PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="3.1.3" />
    <PackgaeReference Include="Microsoft.Extensions.Hosting" Version="3.1.3" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.3" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.3" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.3" />
    <PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.3" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.3" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="1.1.3" />
    <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.2" />
    <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
    <PackageReference Include="Microsoft.AspNetCore.AzureAppServicesIntegration" Version="1.0.2" />
  </ItemGroup>
</Project>

-- Edited - New Update Below. -------------------------------------------------------

Ok, that help by adding "Microsoft.AspNetCore.Identity.UI" NuGet package. Now I have run into another error. :-/ I can't make sense of this one.

services.AddDefaultIdentity<ApplicationUser>() 
.AddRoles<IdentityRole<Guid>>()
.AddEntityFrameworkStores<ApplicationContext, Guid>() 
.AddDefaultTokenProviders();

The error on the first line is gone now. But now new error on 3rd line here, "AddEntityFrameworkStore<ApplicationContext, Guid>()". The error message is --> "IdentityBuilder" does not contain a definition for "AddEntityFrameworkStores" & no accessible extension method "AddEntityFrameworkStores" accepting a first argument of type "IdentityBuilder" could be found (are you mising a using directive or an assembly reference?).

Not even sure what NuGet package does this "AddEntityFrameworkStores" come from & what have changed from version 1 to 3.1 either.

like image 401
fletchsod Avatar asked May 05 '20 17:05

fletchsod


2 Answers

You would need to add a reference to the Microsoft.AspNetCore.Identity.UI nuget package in order to use AddDefaultIdentity. But if you don't want to migrate to the Identity Razor Class Library I think you can still use .AddIdentity<ApplicationUser, IdentityRole>() in core 3.1. If you do want to migrate to the RCL, the Migration documentation for 2.0 to 2.1 might be a good starting place: https://docs.microsoft.com/en-us/aspnet/core/migration/20_21?view=aspnetcore-3.1#changes-to-authentication-code

--- Edited ---

I've migrated a few sites from 1.1 to 3.1 and the easiest way I have found to do it is this:

  1. Move your entire solution to a backup folder (make sure to leave your source control files where they are).
  2. Create a new application in your original location with the exact same name that targets 3.1. I use the "Web Application (Model-View-Controller)" template in VS 2019 and change the authentication to "Individual User Accounts".
  3. Commit that to source control so you can see what changes you make.
  4. Copy all of your pages, views controllers, and other code to the new application.
  5. Add back any missing nuget packages.
  6. You will probably need to make some changes to your copied code but you can use the changes in source control and the migration docs for a reference point.

It still takes a lot to get it working but otherwise you will need to go through every migration doc starting with the one for 1.x to 2.0 all the way through the doc for 3.0 to 3.1.

like image 196
Drew Brasher Avatar answered Oct 10 '22 16:10

Drew Brasher


I don't know when this got put in, but in AspNetCore 5.0: services.AddIdentityCore<ApplicationUser>() works. Contains type requirement for TUser only.

like image 32
spencer741 Avatar answered Oct 10 '22 14:10

spencer741