I have successfully linked aspnetusers table to my custom users table as one-to-one relationship. Now when i go to register all information is successfully added to both tables except one thing - Id.
My pk userId in users table is an AutoIncrement key and i wish to add the same value in the id field of aspnetUsers table. I think i will have to override createAsync or do i remove from SignInAsync
await user.GenerateUserIdentityAsync(UserManager)
Inside AccountController Register method, I have
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var geUser = new User { Password = model.Password, Username = model.Email, AccessLevel = "0003", LoggedIn = false, Active = true, AllowOffline = false, LastSettingsRefreshed = DateTime.Now };
var user = new ApplicationUser() { UserName = model.Email, Email = model.Email, user = geUser};
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInAsync(user, isPersistent: false);
return RedirectToAction("Index", "Home");
}
else
{
AddErrors(result);
}
}
return View(model);
}
My Data Tables:
ASPNetUSers and Users respectively:
I want to enter 43 instead of 0 in aspnetusers table
UPDATE
On research i see that it has something to do with DatabaseGeneratedOption but exactly what and on which table should i do "DatabaseGeneratedOption.None"?
Related
I'm going to have a subscription flow as follows:
User goes to pricing page, chooses plan, is redirected to ../Register?planId=1
User registers with username and password, is forwarded to billing page, which needs to be ../Subscription/Billing?planId=1
I added an integer, planId, to my RegisterViewModel
On pricing page, I have the links working correctly.
For register controller, I have:
[AllowAnonymous]
public ActionResult Register(RegisterViewModel model, int planId)
{
if (Request.IsAuthenticated) {
return RedirectToAction("Pricing", "Home");
}
RegisterViewModel model1 = new RegisterViewModel();
model1.planId = Convert.ToInt32(Request.QueryString["planId"]);
return View(model1);
}
And in Register view I have:
#Html.HiddenFor(m => m.planId)
However, this value is blank everytime I've run the application. If I can get the planId to be included as part of the register form submission, then I think I can redirect the controller to "../Subscription/Billing?planId=1" after registration.
Here's the current register post controller, where I think I just need to add the planid to the redirectToAction:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email, Role = "Admin", ReportsTo = "", ActiveUntil = DateTime.Now.AddDays(-1) };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
// For more information on how to enable account confirmation and password reset please visit http://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 here");
return RedirectToAction("Pricing", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
My question is, how do I get the planid to pass from the query string to a hidden field in the login form?
You can try model1.planId = planId
Well im kind wasting too much time trying to accomplish this objective and im kinda frustrated, what i want to do is something like that:
**table aspNetUserRoles
userId
roleId
table aspNetRole
roleId
RoleName**
i already did the first part i already filled the aspNetUserRoles with the seed method and have some roles in my database, and i already created a dropdownlist with all my roles, but i have a problem when i press Register i get a error : "UserId not found" i will show here what i alrady did and will place my 2 tables
what i did
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email, Sobre = model.Sobre, Idade = model.Idade, Telemóvel = model.Telemóvel, Nome = model.Nome };
var result = await UserManager.CreateAsync(user, model.Password);
var roleStore = new RoleStore<IdentityRole>(db);
var roleManager = new RoleManager<IdentityRole>(roleStore);
var userStore = new UserStore<ApplicationUser>(db);
var userManager = new UserManager<ApplicationUser>(userStore);
userManager.AddToRole(user.Id, "Name");
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
// For more information on how to enable account confirmation and password reset please visit http://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 here");
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
if someone can me explain what i am doing wrong i appreciate a lot :)
use Like this
if (result.Succeeded)
{
userManager.AddToRole(user.Id, "Name");
}
I am creating Employee registration form. I have stored UserName ,Password and Role field in Login table and address, phon no. and as shown below details in employee table. As per my knowledge I have tried all efforts but this create method is not working... Please help me
public ActionResult Create(EmployeeViewModel model)
{
if (ModelState.IsValid)
{
var search = db.Logins.FirstOrDefault(x => x.UserEmail == model.UserEmail);
if (search != null)
{
ViewBag.Message = "Email you've enter is used by someone else. Reenter please";
}
else
{
Login login = new Login
{
UserEmail = model.UserEmail,
UserPass = (model.UserPass),
RoleID = 2,
Created = DateTime.Now,
IsVerified = true
};
db.Logins.Add(login);
db.SaveChanges();
DivineDemo.Employee emp = new DivineDemo.Employee
{
EmpID = login.UserID,
EmpName = model.EmpName,
Address = model.Address,
CityID = model.CityID,
PhoneNo = model.PhonNo,
Gender = model.Gender
//JoinDate = DateTime.Now
};
db.Employees.Add(emp);
db.SaveChanges();
ViewBag.Message = "Employee added successfully";
ModelState.Clear();
}
}
return View(model);
}
I found my ans by examining the locals from debug. Modelstate.isvalid method was turned to false thatsway values are not inserted in db
I've built an MVC 5 website. Adding a user generates and sends an email with a confirmation token. When the user clicks the emailed link, the site responds, asking the user to set an initial password.
When the user tries to set an initial password, the user has not logged in yet, so User.Identity.GetUserId() is null. How do I pass the user ID from the confirmation link to the call to SetPassword()?
AccountController.cs
// GET: /Account/ConfirmEmail
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
return View("Error");
var result = await UserManager.ConfirmEmailAsync(userId, code);
if (result.Succeeded)
using (var s = new UserStore())
{
var u = s.FindByIdAsync(userId).Result;
await s.SetEmailConfirmedAsync(u, true);
return View("ConfirmEmail", new { Id = userId }); // This doesn't seem to make Id available.
}
else
return View("Error");
}
ConfirmEmail.cshtml
#{
ViewBag.Title = "Confirm Email";
}
<h2>#ViewBag.Title.</h2>
<div>
<p>
Thank you for confirming your email.
Please #Html.ActionLink("click here to create a password.",
"SetPassword", "Manage",
routeValues: null, // I've tried passing new { Id = Model.Id }, but Id isn't available at run-time.
htmlAttributes: new { id = "loginLink" })
</p>
</div>
ManageController.cs
// POST: /Manage/SetPassword
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> SetPassword(SetPasswordViewModel model)
{
if (ModelState.IsValid)
{
var result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
if (result.Succeeded)
{
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (user != null)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
}
return RedirectToAction("Index", new { Message = ManageMessageId.SetPasswordSuccess });
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
A simple fix is to add a parameter to the SetPassword method:
public async Task<ActionResult> SetPassword(SetPasswordViewModel model, Guid userIdentifier)
The ConfirmEmail.cshtml would then change to:
Please #Html.ActionLink("click here to create a password.",
"SetPassword", "Manage",
routeValues: null, // I've tried passing new { Id = Model.Id }, but Id isn't available at run-time.
htmlAttributes: new { id = "loginLink", userIdentifier = Model.ID })
When the user clicks the link, you should now have the userIdentifier filled in with the ID of the user the email was sent to.
It's not super secure as they can pass any Guid (if they can figure out which one to send).
You may want to track a PasswordRequest object by ID (instead of userIdentifier) that can expire the email in which case they need to request a new one. This way once the PasswordRequest record is used, it can be deleted to prevent reuse as well.
Note: PasswordRequest is just a made up name.
You collect the password when you first create a user so that you don't need an id for your UserManager.CreateAsync(). You'd send the confirmation email token in the register action after you've created a new row (and generated the id).
The SetPassword() action is for an existing and authenticated user to change their password. You should not mark that as [AllowAnonymous].
you can use the query string, in the confirmation token you can encrypt the username or userid and when you reach the reset page decrypt it and set the Identity to whoever it was.
Edit: In addition to that you can create a new table in the database InitialSetup, with columns user, EncryptedId(guid), Initial.
When someone clicks the email link they will need to input username, and new password. That is when you will check if the input username is the same as the EncryptedId(guid).
I am using asp.net identity for login and authentication.
I am getting error for password field when login with following method
model= is user entity
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
bool isPersistent = false;
await SignInAsync(user, isPersistent);
return RedirectToLocal(returnUrl);
}
The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters
Are you using EF? If so, you shouldnt add AspNetRoles, AspNetUserClaims, AspNetUserLogins and AspNetUserRoles on your edmx.
In addition, I always use "Login" method like below. If I need to keep some info (like userRole, userName etc), I use Session like below.
public async Task<ActionResult> Login(LoginViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var user = await UserManager.FindAsync(model.Email, model.Password);
//var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
if (user != null)
{
string userRole = UserManager.GetRoles(user.Id).FirstOrDefault();
Session["userRole"] = userRole;
Session["userName"] = model.Email;
await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "Invalid username or password");
return View(model);
}
}
Hence can you try
await SignInManager.PasswordSignInAsync
or
await SignInManager.SignInAsync