I am unable to use RoleManager in my application. I am trying to seed an Admin user in to a .NET Core web application, and I want this user to have a role called "canEdit". What I've got currently produces this error:
System.InvalidOperationException: 'No service for type 'Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole]' has been registered.'
I have tried various ways of doing this. I have tried using Service Provider to do it, dependency injection, etc. but they all give the same error.
ServiceProvider in the Configure method of Startup.cs:
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
var scopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>();
var scope = scopeFactory.CreateScope();
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
DbInitializer dbi = new DbInitializer(roleManager);
dbi.Initialize(context, userManager);
DBInitializer Class:
Constructor:
private readonly RoleManager<IdentityRole> rm;
public DbInitializer(RoleManager<IdentityRole> rm)
{
this.rm = rm;
}
CreateAdmin method:
private async Task CreateAdmin(UserManager<ApplicationUser> userManager, ApplicationDbContext context)
{
IdentityResult ir;
ir = await rm.CreateAsync(new IdentityRole("canEdit"));
IdentityRole canEdit = new IdentityRole("canEdit");
ApplicationUser admin = new ApplicationUser
{
UserName = "Member1#email.com"
};
if (context.Users.Where(u => u.UserName == admin.UserName).Count() == 0)
{
userManager.CreateAsync(admin, "Password123!").Wait();
userManager.AddToRoleAsync(admin, "canEdit").Wait();
}
}
CreateUsers method:
private void CreateUsers(UserManager<ApplicationUser> userManager, ApplicationDbContext context)
{
CreateAdmin(userManager, context).Wait();
ApplicationUser customer1 = new ApplicationUser
{
UserName = "Customer1#email.com"
};
if (context.Users.Where(u => u.UserName == customer1.UserName).Count() > 0)
{
userManager.CreateAsync(customer1, "Password123!").Wait();
}
This repeats for customer2, 3, 4, 5. I can optimise this by removing the need to create an object which I may not need (in the case where the email exists), but I was trying to knock up this method and the CreateAdmin method quickly, then optimise later. Unfortunately I then ran in to an error which I have been unable to fix.
The end goal is for the DbInitializer class to seed 5 regular users, and 1 admin user with extra permissions/claims.
Do you have the Identity services registered?
Also, I ran into issues when I used .Wait() instead of await.
services.AddIdentity<ApplicationUser,IdentityRole>(options=>
{
options.User.RequireUniqueEmail = true;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
})
.AddDefaultTokenProviders()
.AddDefaultUI()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthorization();
services.AddAuthentication();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
If this helps, here is how I seeded my Db.
public SeedDataBase(IServiceProvider _serviceProvider, ApplicationDbContext _context)
{
serviceProvider = _serviceProvider;
context = _context;
}
private IServiceProvider serviceProvider;
private ApplicationDbContext context;
private ApplicationUser superUser;
public async Task Seed()
{
await CreateSuperUser();
await SeedDb();
}
private async Task CreateSuperUser()
{
var _userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
var userExists = await _userManager.GetUsersInRoleAsync("FULLADMIN");
if (userExists.Count() < 1)
{
var _roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var _signinManger = serviceProvider.GetRequiredService<SignInManager<ApplicationUser>>();
superUser = new ApplicationUser()
{
UserName = "superuser#superuser.com",
Email = "superuser#superuser.com",
FirstName = "Super",
LastName = "User",
AccountCreationDate = DateTime.Now.ToShortDateString(),
Access = ApplicationUser.Permissions.FullAdmin
};
var permissions = Enum.GetNames(typeof(ApplicationUser.Permissions));
foreach (var s in permissions)
{
await _roleManager.CreateAsync(new IdentityRole(s));
}
await _userManager.CreateAsync(superUser, "SecureP#ssword1234");
await _userManager.AddToRoleAsync(superUser, Enum.GetName(typeof(ApplicationUser.Permissions), superUser.Access));
}
}
that may help someone in the future ,
you have to use the await for the RoleManager.CreateAsync method
then to verify if the operation was completed successfully
var res = await _roleManager.CreateAsync(new IdentityRole(Role));
if(res.Succeeded)
{
return Ok("created successfully !");
}
If you use IdentityServer4 or Duende.IdentityServer in .NET 5 < with Individual user accounts then edit Startup.cs. Look for the following values:
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
Edit it to look like this:
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
Related
I am trying to use the User Manager for a C# console app in .NET 6 without the help of dependency injection. I manage to construct an instance of the User Manager but when I get to using it (create an email with password reset for my users), I get this error:
No IUserTwoFactorTokenProvider named 'Default' is registered.
Here is where I initialize the User Manager in Program.cs:
IConfiguration config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
IServiceCollection services = new ServiceCollection();
services.AddTransient<UserManager<ApplicationUser>>();
var connectionStrings = config.GetSection("ConnectionStrings");
var messagingConnectionString = connectionStrings.GetValue<string>("Messaging");
AgentConfigDTO appSettingsDTO = new AgentConfigDTO()
{
....
};
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionStrings.ToString(),
sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 5,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null);
}
));
// Register UserManager & RoleManager
services.AddIdentity<IdentityUser, IdentityRole>();
services.AddIdentity<ApplicationUser, IdentityRole>(
options =>
{
options.Tokens.ProviderMap.Add("Default", new TokenProviderDescriptor(typeof(IUserTwoFactorTokenProvider<ApplicationUser>)));
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddTransient<IUserStore<IdentityUser>, UserStore<IdentityUser>>();
services.AddTransient<UserManager<IdentityUser>>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
var optionsBuilderApplication = new DbContextOptionsBuilder<ApplicationDbContext>();
var _applicationContext = new ApplicationDbContext(optionsBuilderApplication.UseSqlServer(connectionStrings.ToString()).Options);
IUserStore<ApplicationUser> store = new UserStore<ApplicationUser>(_applicationContext);
UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(store, null, new PasswordHasher<ApplicationUser>(), null, null, null, null, serviceProvider, null);
// UserManager & RoleManager require logging and HttpContext dependencies
services.AddLogging();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
new ReportAgent(appSettingsDTO, messagingConnectionString, userManager).RunAsConsole(args);
And this is the method that runs the User Manager:
public void CheckingPasswords()
{
try
{
var date = DateTime.Now.AddMonths(-3);
var userList = _applicationContext.Users.Where(t => t.PasswordExpiry != null && t.PasswordExpiry <= DateTime.Now.AddMonths(-3) && t.Deleted == false && t.PortalAccessEnabled == true).ToList();
if (userList.Count > 0)
{
// Create email
foreach (var user in userList)
{
// Lock user out of the account
user.PortalAccessEnabled = false;
_applicationContext.Update(user);
_applicationContext.SaveChanges();
// Create email
// Exception is thrown on this line of code
var code = _userManager.GeneratePasswordResetTokenAsync(user).ToString();
var url = .
var callbackUrl = url.Replace("[[id]]", user.Id).Replace("[[code]]", code);
Email email = new()
{
...
};
_dbContext.Add(email);
_dbContext.SaveChanges();
}
}
}
}
I am now stuck with this and have no idea how to fix it.
I've also tried manually adding in the Token Provider but that didn't make any difference:
var identityBuilder = new IdentityBuilder(typeof(ApplicationUser), typeof(IdentityRole<string>), services);
identityBuilder.AddTokenProvider("Default", typeof(DataProtectorTokenProvider<ApplicationUser>));
services.AddTransient<UserManager<ApplicationUser>>();
The error message "No IUserTwoFactorTokenProvider named 'Default' is registered" is because you are missing the configuration for the default two-factor token provider. To resolve this, you need to register the default two-factor token provider for UserManager in the services collection.
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddTransient<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>();
services.AddTransient<UserManager<ApplicationUser>>();
services.AddLogging();
services.AddHttpContextAccessor();
}
}
public class ConsoleApp
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly ApplicationDbContext _applicationContext;
public ConsoleApp(UserManager<ApplicationUser> userManager, ApplicationDbContext applicationContext)
{
_userManager = userManager;
_applicationContext = applicationContext;
}
public void CheckingPasswords()
{
try
{
var date = DateTime.Now.AddMonths(-3);
var userList = _applicationContext.Users.Where(t => t.PasswordExpiry != null && t.PasswordExpiry <= DateTime.Now.AddMonths(-3) && t.Deleted == false && t.PortalAccessEnabled == true).ToList();
if (userList.Count > 0)
{
//Create email
foreach (var user in userList)
{
// Lock user out of the account
user.PortalAccessEnabled = false;
_applicationContext.Update(user);
_applicationContext.SaveChanges();
//Create email
var code = _userManager.GeneratePasswordResetTokenAsync(user).Result;
var url = .
var callbackUrl = url.Replace("[[id]]", user.Id).Replace("[[code]]", code);
Email email = new()
{
...
};
_dbContext.Add(email);
_dbContext.SaveChanges();
}
}
}
}
}
This question already has answers here:
How to access DbContext in .NET 6 minimal API Program.cs
(1 answer)
how can i use dbInitializer.Initialize() in .net 6.0;
(1 answer)
Closed 3 months ago.
I'm coding a website using ASP.NET Core 6 from the course. The course was released in winter 2022 with old middleware. So I am facing problems with it. Here I have a DbInitializer file that contains user initialization data.
System.InvalidOperationException: 'Cannot resolve scoped service 'Mango.Services.Identity.Initializer.IDbInitializer' from root provider.'
DbInitializer.cs:
public class DbInitializer : IDbInitializer
{
private readonly ApplicationDbContext _context;
private readonly UserManager<ApplicationUser> \userManager;
private readonly RoleManager<IdentityRole> _roleManager;
public DbInitializer(ApplicationDbContext context, UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager)
{
_context = context;
_userManager = userManager;
_roleManager = roleManager;
}
public void Initialize()
{
if (_roleManager.FindByNameAsync(SD.Admin).Result == null)
{
_roleManager.CreateAsync(new IdentityRole(SD.Admin)).GetAwaiter().GetResult();
_roleManager.CreateAsync(new IdentityRole(SD.Customer)).GetAwaiter().GetResult();
}
else
{
return;
}
ApplicationUser adminUser = new ApplicationUser()
{
UserName = "admin#gmail.com",
Email = "admin#gmail.com",
EmailConfirmed = true,
PhoneNumber = "111111111",
FirstName = "Ben",
LastName = "Admin"
};
_userManager.CreateAsync(adminUser,"Admin123").GetAwaiter().GetResult();
_userManager.AddToRoleAsync(adminUser, SD.Admin).GetAwaiter().GetResult();
var temp1 =_userManager.AddClaimsAsync(adminUser, new Claim[]{
new Claim(JwtClaimTypes.Name, adminUser.FirstName+" "+ adminUser.LastName),
new Claim(JwtClaimTypes.GivenName, adminUser.FirstName),
new Claim(JwtClaimTypes.FamilyName, adminUser.LastName),
new Claim(JwtClaimTypes.Role, SD.Admin)
}).Result;
ApplicationUser customerUser = new ApplicationUser()
{
UserName = "customer1#gmail.com",
Email = "customer1#gmail.com",
EmailConfirmed = true,
PhoneNumber = "111111111",
FirstName = "Ben",
LastName = "Cust"
};
_userManager.CreateAsync(customerUser, "Admin123").GetAwaiter().GetResult();
_userManager.AddToRoleAsync(customerUser, SD.Customer).GetAwaiter().GetResult();
var temp2 = _userManager.AddClaimsAsync(customerUser, new Claim[]{
new Claim(JwtClaimTypes.Name, customerUser.FirstName+" "+ customerUser.LastName),
new Claim(JwtClaimTypes.GivenName, customerUser.FirstName),
new Claim(JwtClaimTypes.FamilyName, customerUser.LastName),
new Claim(JwtClaimTypes.Role, SD.Customer)
}).Result;
}
}
Then my Program.cs file:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();
var identityBuilder = builder.Services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
options.EmitStaticAudienceClaim = true;
}).AddInMemoryIdentityResources(SD.IdentityResourses)
.AddInMemoryApiScopes(SD.ApiScopes)
.AddInMemoryClients(SD.Clients)
.AddAspNetIdentity<ApplicationUser>();
builder.Services.AddScoped<IDbInitializer, DbInitializer>();
identityBuilder.AddDeveloperSigningCredential();
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthorization();
app.Services.GetRequiredService<IDbInitializer>().Initialize();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
I myself have not so long started to dive into the world of asp.net core coding and therefore encounter such problems. Can you tell me how to solve this problem? All the ways I found did not help.
In ASP.NET Core 6 Web API, I am implementing EF migration seeding. When I used .NET Core 5, I applied it in Startup.cs and it works there.
public static class AppDbContextSeed
{
public static void SeedData(UserManager<ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager)
{
SeedRoles(roleManager);
SeedUsers(userManager);
}
public static void SeedRoles(RoleManager<ApplicationRole> roleManager)
{
if (!roleManager.RoleExistsAsync("Admin").Result)
{
ApplicationRole role = new ApplicationRole();
role.Name = "Admin";
IdentityResult roleResult = roleManager.
CreateAsync(role).Result;
}
if (!roleManager.RoleExistsAsync("Student").Result)
{
ApplicationRole role = new ApplicationRole();
role.Name = "Student";
IdentityResult roleResult = roleManager.
CreateAsync(role).Result;
}
}
public static void SeedUsers(UserManager<ApplicationUser> userManager)
{
if (userManager.FindByNameAsync("admin").Result == null)
{
ApplicationUser user = new ApplicationUser()
{
UserName = "admin",
Email = "admin#africa.email.com",
FirstName = "AdminFN",
LastName = "AdminLN",
NormalizedUserName = "ADMIN"
};
IdentityResult result = userManager.CreateAsync
(user, "Admin*123").Result;
if (result.Succeeded)
{
userManager.AddToRoleAsync(user, "Admin").Wait();
}
}
}
}
But now I am using .NET Core 6. So when I applied this in Program.cs:
public void Configure(UserManager<ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager)
{
// DB Seeding
AppDbContextSeed.SeedData(userManager, roleManager);
}
I got this error:
The local function 'Config' is declared but never used
Error CS0106: the modifier 'public' is not valid for this item
How do I correct the error and replicate this in .NET Core 6?
Thank you.
I had to edit my last answer, the example I gave was for .net5. Here is .net 6, I haven't tested it myself but it should work.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
Configure(app);
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
void Configure(WebApplication host)
{
using var scope = host.Services.CreateScope();
var services = scope.ServiceProvider;
try
{
var dbContext = services.GetRequiredService<MyDatabaseContext>();
if (dbContext.Database.IsSqlServer())
{
dbContext.Database.Migrate();
}
var userManager = services.GetRequiredService<UserManager<ApplicationUser>>();
var roleManager = services.GetRequiredService<RoleManager<ApplicationRole>>();
AppDbContextSeed.SeedData(userManager, roleManager);
}
catch (Exception ex)
{
//Log some error
throw;
}
}
I am trying to get a users Roles after they log in via Single Sign On. The problem is that the UserManager and RoleManager objects are always null. From what I have read online, is seems like these objects should be created via injection, but I am not sure what I am doing wrong. Here is my code (if I am missing anything relevant, please let me know and I will edit my question). I also did not see a tag for "Microsoft.AspNetCore.Identity" so apologies if this is not tagged correctly (the error is in the last function "TransformClaims"):
Startup.cs
using Microsoft.AspNetCore.Identity;
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//.....
app.UseAuthentication();
app.UseAuthorization();
//.....
}
public void ConfigureServices(IServiceCollection services)
{
//.....
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("ApplicationDbContextConnection")));
services.AddIdentity<CustomUserContext, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.Configure<IdentityOptions>(options =>
options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier);
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<CustomUserContext>>();
services.AddAuthorizationCore();
ConfigureSSO(services);
services.AddTransient<UserManager<USAIDUserContext>>();
services.AddTransient<ApplicationDbContext>();
//.....
}
public void ConfigureSSO(IServiceCollection services){
//code to provide SSO
//relevant code is when SSO returns token validation
OnTokenValidated = async ctxt =>
{
Trace.TraceInformation("Token validated");
ctxt.Properties.IsPersistent = true;
ctxt.Properties.IssuedUtc = DateTime.Now;
ctxt.Properties.ExpiresUtc = DateTime.Now.AddDays(1);
ClaimsPrincipal claimPrinciple = ctxt.Principal;
ClaimsIdentity ClaimsID = await TransformClaims(claimPrinciple);
await Task.Yield();
},
}
private async Task<ClaimsIdentity> TransformClaims(ClaimsPrincipal principal)
{
ClaimsIdentity appIdentity = null;
if(principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
else
{
//gets loggedin email, which is stored in database
var loggedInUserId = principal.Claims.FirstOrDefault(c => c.Type == "email")?.Value;
RoleManager<IdentityRole> _rolemanager;
UserManager<CustomUserContext> _userManager;
//both RoleManager and UserManager are null, causing the functions below to have an error about object being null
var user = await _userManager.FindByEmailAsync(loggedInUserId);
var roles = await _userManager.GetRolesAsync(user);
}
return appIdentity;
}
Edit
AddRolesClaimsTransformation.cs
public class AddRolesClaimsTransformation : IClaimsTransformation
{
private readonly IUserService _userService;
public AddRolesClaimsTransformation(IUserService userService)
{
_userService = userService;
}
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
// Code Never Hit
var clone = principal.Clone();
var newIdentity = (ClaimsIdentity)clone.Identity;
// Support AD and local accounts
var nameId = principal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier ||
c.Type == ClaimTypes.Name);
if (nameId == null)
{
return principal;
}
// Get user from database
var userResponse = await _userService.GetAsync(nameId.Value);
return clone;
}
}
public interface IUserService
{
Task<USAIDUserContext> GetAsync(string id);
}
}
This is my implementation, you can find the constructor of the class that implement the interface.
I've injected IUserService and inside the constructor of UserService class I've added injection for UserManager and RoleManager.
public class AddRolesClaimsTransformation : IClaimsTransformation
{
private readonly IUserService _userService;
public AddRolesClaimsTransformation(IUserService userService)
{
_userService = userService;
}
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
// Clone current identity
var clone = principal.Clone();
var newIdentity = (ClaimsIdentity)clone.Identity;
// Support AD and local accounts
var nameId = principal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier ||
c.Type == ClaimTypes.Name);
if (nameId == null)
{
return principal;
}
// Get user from database
var userResponse = await _userService.GetAsync(nameId.Value);
if (!userResponse.Succeeded || userResponse.Data is null)
{
return principal;
}
var user = userResponse.Data;
var rolesResponse = await _userService.GetRolesAsync(user.Id);
...
return clone;
}
}
This is an example of a method inside UserService:
public async Task<IResult<UserResponse>> GetAsync(string userId)
{
var user = await _userManager.Users.Where(u => u.Id.ToString() == userId).FirstOrDefaultAsync();
var result = _mapper.Map<UserResponse>(user);
return await Result<UserResponse>.SuccessAsync(result);
}
I'm trying to create some roles for my web application but it isn't really working because of a Tkey exception.
I'm happy if you give an upvote so the other guys who need help can see it probably more.
I don't know how I can fix it. I think there is a problem with my Startup.cs.
Whatever i try to add the DefaultIdentity and adding the roles.
Startup.cs - On this line I get an Error:
services.AddDefaultIdentity<IdentityRole>().AddRoles<IdentityRole>().AddDefaultUI().AddEntityFrameworkStores<VerwaltungsprogrammContext>();
This is the Error Message:
>AddEntityFrameworkStores can only be called with a user that derives from IdentityUser
namespace Verwaltungsprogramm
{
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.AddSession();
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<VerwaltungsprogrammContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("VerwaltungsprogrammContext")));
//services.AddDefaultIdentity<IdentityUser>();
--------------> services.AddDefaultIdentity<IdentityRole>().AddRoles<IdentityRole>().AddDefaultUI().AddEntityFrameworkStores<VerwaltungsprogrammContext>(); <--------------
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddRazorPagesOptions(options =>
{
options.AllowAreas = true;
options.Conventions.AuthorizeAreaFolder("Logins", "/Create");
options.Conventions.AuthorizeAreaPage("Logins", "/Logout");
});
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = $"/Logins/Index";
options.LogoutPath = $"/Logins/Logout";
options.AccessDeniedPath = $"/Cars/Index";
});
//Password Strength Setting
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.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._#+";
options.User.RequireUniqueEmail = false;
});
//Seting the Account Login page
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
options.LoginPath = "/Logins/Create"; // If the LoginPath is not set here, ASP.NET Core
will default to /Account/Login
options.AccessDeniedPath = "/Cars/Index"; // If the AccessDeniedPath is not set here,
ASP.NET Core will default to /Account/AccessDenied
options.SlidingExpiration = true;
});
services.AddSingleton<IEmailSender, EmailSender>();
}
public class EmailSender : IEmailSender
{
public Task SendEmailAsync(string email, string subject, string message)
{
return Task.CompletedTask;
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
Seed.CreateRoles(serviceProvider, Configuration).Wait();
}
}
}
Error:
AddEntityFrameworkStores can only be called with a user that derives from IdentityUser
The Seed.cs file is to create some roles
Here is my Seed.cs
namespace Verwaltungsprogramm
{
public static class Seed
{
public static async Task CreateRoles(IServiceProvider serviceProvider, IConfiguration Configuration)
{
//adding customs roles
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var UserManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
string[] roleNames = { "Admin", "Manager", "Member" };
IdentityResult roleResult;
foreach (var roleName in roleNames)
{
// creating the roles and seeding them to the database
var roleExist = await RoleManager.RoleExistsAsync(roleName);
if (!roleExist)
{
roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
}
}
// creating a super user who could maintain the web app
var poweruser = new ApplicationUser
{
UserName = Configuration.GetSection("AppSettings")["UserEmail"],
Email = Configuration.GetSection("AppSettings")["UserEmail"]
};
string userPassword = Configuration.GetSection("AppSettings")["UserPassword"];
var user = await UserManager.FindByEmailAsync(Configuration.GetSection("AppSettings")["UserEmail"]);
if (user == null)
{
var createPowerUser = await UserManager.CreateAsync(poweruser, userPassword);
if (createPowerUser.Succeeded)
{
// here we assign the new user the "Admin" role
await UserManager.AddToRoleAsync(poweruser, "Admin");
}
}
}
}
}
Does the error also occur if you write the line in your Startup.cs like this?
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<VerwaltungsprogrammContext>();
I fixed it by creating the project again and switch to user Account authentication, for everyone who has the same problem, I recommend doing that.