'Identity UserManager CreateAsync does not write to database
It doesn't give any errors or warnings but it doesn't insert in the database. Seems like it's only in memory.
Also UserManager's FindByNameAsync can't check users already created in the database, probably for the same reason.
Here is my Controller:
public class AccountController : Controller
{
private readonly UserManager<User> _userManager;
private readonly SignInManager<User> _signInManager;
public AccountController(UserManager<User> userManager, SignInManager<User> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(User user)
{
if (ModelState.IsValid)
{
var result = await _userManager.CreateAsync(user, user.Password);
if (result.Succeeded)
{
Console.WriteLine("OK");
}
var username = await _userManager.FindByNameAsync(user.UserName);
if (username != null)
{
//sign in
var signInResult = await _signInManager.PasswordSignInAsync(user.UserName, user.Password, false, false);
if (signInResult.Succeeded)
{
return RedirectToAction("Index", "ProjectCampaign");
}
}
}
return View();
}
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
return RedirectToAction("Login", "Account");
}
}
Startup.cs
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.AddDbContext<RandomContext>(config =>
{
config.UseInMemoryDatabase("Memory");
});
services.AddIdentity<User, Role>(config => {
config.Password.RequireDigit = false;
config.Password.RequiredLength = 4;
config.Password.RequireNonAlphanumeric = false;
config.Password.RequireUppercase = false;
})
.AddEntityFrameworkStores<RandomContext>()
.AddDefaultTokenProviders();
services.ConfigureApplicationCookie(config =>
{
config.Cookie.Name = "AuthCookie";
config.LoginPath = "/Account/Login";
config.ExpireTimeSpan = TimeSpan.FromMinutes(1);
});
services.AddScoped<RandomContext>();
services.AddControllersWithViews().AddRazorRuntimeCompilation();
}
// 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("/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.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
User.cs
public partial class User : IdentityUser<int>
{
public int ID { get; set; }
[Required(ErrorMessage = "Username is required")]
public override string UserName { get; set; }
[Required(ErrorMessage = "Password is required")]
public string Password { get; set; }
}
RandomContext.cs
public partial class RandomContext : IdentityDbContext<User, Role, int>
{
public RandomContext()
{
}
public RandomContext(DbContextOptions<RandomContext> options)
: base(options)
{
}
public virtual DbSet<ProjectCampaign> ProjectCampaigns { get; set; }
public virtual DbSet<Role> Roles { get; set; }
public virtual DbSet<User> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
optionsBuilder.UseSqlServer("Server=.;Database=Random;Trusted_Connection=True;");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ProjectCampaign>(entity =>
{
entity.ToTable("ProjectCampaign");
entity.Property(e => e.Id).HasColumnName("ID");
entity.Property(e => e.Campaign)
.HasMaxLength(50)
.IsUnicode(false);
entity.Property(e => e.CreateDate)
.HasColumnType("datetime")
.HasDefaultValueSql("(getdate())")
.HasAnnotation("Relational:ColumnType", "datetime");
entity.Property(e => e.Project)
.HasMaxLength(50)
.IsUnicode(false);
});
modelBuilder.Entity<Role>(entity =>
{
entity.Property(e => e.Id).HasColumnName("ID");
entity.Property(e => e.CreateDate)
.HasColumnType("datetime")
.HasDefaultValueSql("(getdate())")
.HasAnnotation("Relational:ColumnType", "datetime");
entity.Property(e => e.Description)
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false);
});
modelBuilder.Entity<User>(entity =>
{
entity.Property(e => e.Id).HasColumnName("ID");
entity.Property(e => e.Password).IsRequired();
entity.Property(e => e.UserName)
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false);
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
If you need more detail please let me know.
Solution 1:[1]
I had similar problem - AspNetCore.Identity.UserManager
did not throw any errors but did not write entry to database on CreateAsync(user, password)
. However, when I debugged the UserManager
I could see there was a single entry in the PasswordValidators
array.
Basically, the entered password was not complex enough. Changed the password and everything worked.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |