I have been experimenting with MVC5/EF6 and trying out the new Identity Authentication with Code-First Migrations. Everything in the solution is currently building and I can
the issue in my case is that i use (Username) of user instead of Id, working code below:
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Username, Email = model.Username, workshopId =model.workshopId};
var rolesList = _context.Roles.ToList();
string role = rolesList.FirstOrDefault(r => r.Id == model.SelectedRoleId).Name;
var result = await UserManager.CreateAsync(user, model.Password);
// Add User to the selected role from the list in .cshtml
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
result =await UserManager.AddToRoleAsync(user.Id, role);
// For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
// string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
// var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
// await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
I would avoid using the UserManager and RoleManager in your Seed method. Instead I would only use the context. Something I use is the following which creates a user and assigns him to a role:
protected override void Seed(DbModelContext context)
{
if (context == null)
{
throw new ArgumentNullException("context", "Context must not be null.");
}
const string UserName = "User";
const string RoleName = "UserRole";
var userRole = new IdentityRole { Name = RoleName, Id = Guid.NewGuid().ToString() };
context.Roles.Add(userRole);
var hasher = new PasswordHasher();
var user = new IdentityUser
{
UserName = UserName,
PasswordHash = hasher.HashPassword(UserName),
Email = "test@test.com",
EmailConfirmed = true,
SecurityStamp = Guid.NewGuid().ToString()
};
user.Roles.Add(new IdentityUserRole { RoleId = userRole.Id, UserId = user.Id });
context.Users.Add(user);
base.Seed(context);
}
The Entity classes are custom implementations (because I wanted to use GUIDs as the IDs), but they derive from the framework classes. With that it should work in the same way if you change them to the appropriate framework classes.
EDIT
I removed the custom classes and switched them to the framework classes, because there were some confusion.
This saved my 2nd day . Thanks @Daffy Punk. In my case the issue was password. which was "abc" before.
var studentPassword = "abcABC_9";
var user = new ApplicationUser { UserName = "abc", Email = 1@gmail.com };
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var result = await UserManager.CreateAsync(user, studentPassword.ToString());
await UserManager.AddToRoleAsync(user.Id, "Student");
CraftBeerHipsterDude's answer helped me find the answer to the same situation I had. If AddToRole fails, the trick is to look at the result returned from Usermanager.Create(...). It might not throw an exception, but still return a results that says the creation failed. In my case it was "Username already exists".
To generalize: Check the results of earlier operations to track down the real error.
I am leaving this here for anyone that might have had a similar issue. I had exactly the same "symptoms". It turns out that the problem related to the password being stored not adhering to the configured password policy (at least one uppercase char, one lowercase char, etc etc).
As per below comments and answers, in general, the same vague error message is thrown when any of the user creation constraints or policies are not followed.
This might include the following:
There is really a wide range of issues which can cause this error to occur. If the above does not solve your problem, I suggest the following:
Answer to the question creator: The UserId should not be entered, leave that to the entity framework to create it for the users.. You are also trying to enter it as an integer, but the Id for users in role based security is a GUID in the form of a string, so it wouldn´t work anyway to try to add an integer value for a column expecting a string.
Now this wasn´t the issue for me, but I had a couple of other issues with the same error:
I tried to figure out what I was missing but found nothing wrong.
So I used another instance of VS as a debugger of the seed code(found this in another thread):
if (System.Diagnostics.Debugger.IsAttached == false)
System.Diagnostics.Debugger.Launch();
I noticed that the user indeed had an Id when it was being added to the role. In the end I was able to do a workaround by adding an empty catch block.. the code doesnt throw exceptions due to a false error and the users are added to the correct roles:
try
{
var newUser = userManager.FindByEmail(superuserToInsert.Email);
userManager.AddToRole(newUser.Id, "Super users");
}
catch
{
}
Before I tried to add a newly created user to a role, the seed seemed to roll back the creation of the user and the user was never created in the user database.
But when I entirely removed the adding to role part, the user was added to the database, and on the second run of a bit edited configuration code, the user could be added to a role, leading me to think it was a a false error being thrown.. ignoring this false error with the empty catch block seems to also ignore the rollback of the user creation(which must happen behind the curtains just before the adding to role part) leading to the user existing when the adding to role part of the code.
Hope it helps someone
EDIT:
The above fixed almost all of my head ache but I noticed there were still some 300 accounts that couldn´t be created(but no errors thrown). A simple FULL OUTER JOIN and examination of the user database with the source database table lead me to think users with a dash(-) character in both the value for "UserName" and "Email" columns stopped the users from being created, and this was the case.
It was an easy fix, just configure the user manager to use more than alphanumeric characters: (and even though the attribute name seems to point to only "User Names" it also affected "Email")
var userManager = new UserManager<ApplicationUser>(userStore);
userManager.UserValidator = new UserValidator<ApplicationUser(userManager)
{
AllowOnlyAlphanumericUserNames = false,
};
//Miske