How save the time of last log in using the SimpleMembership? - simplemembership

I need to save the time, when user loged in.
First I try to realize it in AccountController Login. But now I know, that isn't possible, because User.Id is -1.
Ok, and what can I do to save the time in my user table?
The next problem for me is, when do it. The informations I need to get the user are created after redirect. And the redirect can go everywhere.
An idea is, to get the time on which the ASPXAUTH cookie is set, but I don't know, how to get it.
Is there any solution?

If you need only last login time, you may receive that infrimation from SimpleMembership:
var User = Membership.GetUser("Username") // get user by name
DateTime LastActivityDate = User.LastActivityDate; // get last activity date and time
DateTime LastLogin = User.LastLoginDate; // Last login date and time
DateTime LastPasswordChange = User.LastPasswordChangedDate;

Just learning this stuff myself.
You need to extend the AccountModel, in AccountModel.cs
For example, I added Email to my UserProfile table generation.
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
}
public string Email { get; set; }
I also needed to add it to my RegisterModel further down the file
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[Display(Name = "Email Address")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
The important part here is this new entry:
[Required]
[Display(Name = "Email Address")]
public string Email { get; set; }
Then I needed to add the Email information to the RegisterView, which is exactly the same as doing it with the other parts, since it is now part of the model.
One of the most important parts comes when you're saving the information back into the database. In my Register Action, I have the WebSecurity.CreateUserAndAccount method which was already defined. It requires tweaks however, to be able to add EXTRA information to the database with this method.
Thankfully one of the overloads allows passing in a dictionary to the extra data.
WebSecurity.CreateUserAndAccount(model.UserName, model.Password, new { Email = model.Email }, false);
new { Email = model.Email }
If you don't already have the column added in your database, I don't think it will pick it up. You need to make sure that column exists, so get it set up before hand.

Related

.Net Core Identity Add Company Name As Part Of User Login Process In .Net Core 5.0

Is it possible to use additional user fields for user login in .Net Core Identity? I want to allow logging in users using email, password, and a third field i.e Company Name which is a custom field I defined in ApplicationUser class inherited from IdentityUser class.
My ApplictionUser class:
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
}
It is working fine. I can add the company name for the user during registration.
Here is the identity InputModel code which is created by identity scaffolding:
public class InputModel
{
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required]
[Display(Name = "Company Name")]
public string CompanyName { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
I added the CompanyName extra field here. Now I want to log in the user based on these fields. If the company name provided by the user on the login page is correct, allow the user to login otherwise not.
I am doing the following custom code inside OnPostAsync method of Login.cshtml.cs file:
var user = await _userManager.FindByEmailAsync(Input.Email);
ApplicationUser user = new ApplicationUser
{
Email = Input.Email,
UserName = Input.Email,
CompanyName = Input.CompanyName,
};
var result = await _signInManager.PasswordSignInAsync(user, Input.Password, Input.RememberMe, lockoutOnFailure: false);
But the result is always getting failed for every attempt. Am doing anything wrong here?
You appear to be overwriting the user object with your new implementation, which wouldn't have the password hash to check against (amongst other things).
It may be simpler to check the user for the correct company name directly and throw the error if it doesn't match, as follows:
var user = await _userManager.FindByEmailAsync(Input.Email);
if (user == null || user.CompanyName != Input.CompanyName) {
ModelState.AddModelError("", "Invalid login attempt");
return View(model);
}
var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);

Required field is not working in mvc4

in my model i have email, password,new password and re-type new password property's are there.
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email: ")]
public string Email { get; set; }
public bool changePassword { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Old Password:*")]
public string OldPassword { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "New Password:*")]
public string NewPassword { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Re-type Password:*")]
i put required to all controls.
in my view i devide those controls like, Email in one form and remaining are another form. my problem is email validation is working in form form.
coming to another form validation is not working.
can any one suggest me to come out this problem.
in your cshtml file say layout try putting this
#Scripts.Render("~/Scripts/jquery.validate.min.js")
#Scripts.Render("~/Scripts/jquery.validate.unobtrusive.min.js")
this might work.
Make sure that you are submitting to proper controller and using the ModelState.IsValid
// POST: /Orders/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Orders order) {
if (ModelState.IsValid) {
try {
.....

SelectList when using EditorFor

i have come across a strange behaviour when trying to get a SelectList to display correctly when using the Html.EditorForModel().
I have the following Model:
public class LoginModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
public string Gender { get; set; }
[UIHint("SelectList")]
public SelectList AvailibleGender { get; set; }
}
As you can see, I have a SelectList item that holds the values to get put into the Gender string. I have overriden the SelectList EditorTemplate, which for now has a simple script tag showing an alert box.
When I use EditorFor(m=>AvailableGender), my alert box fires, which means the editor correctly chose my SelectList template.
When I use EditorForModel(), my alert box does not fire.
If I change the model as follows:
[UIHint("SelectList")]
public string AvailibleGender { get; set; }
..then my SelectList template does get hit, and I see the alert message.
So it looks like there is something specifically blocking the SelectList.
In case it is something to do with specific custom types, I tried adding an object.cshtml file, but this doesn't get invoked either. so it seems that the SelectList type is getting lost somewhere.
Does anyone have any ideas on how to get the Select List working with EditorForModel()?

SimpleMembership - Add email to UserProfile - System.Data.SqlClient.SqlException: Invalid column name "Email" error

I'm fairly sure I have followed all the steps, but seem to have missed something. Using simplemembership in MVC4 app. Add Email to UserProfile table and in the Register and UserProfile models, added it to the Register method, but still getting the error. Here is some code:
Models:
public class UserProfile
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
}
public class RegisterModel
{
[Display(Name = "Email Address")]
[StringLength(20)]
// [Required]
public string Email { get; set; }
[Display(Name = "Date of Birth")]
// [Required]
public DateTime DOB { get; set; }
[Required]
[System.Web.Mvc.Remote("VerifyUserExists", "Account", ErrorMessage="That Username is already taken.")]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
Controller:
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password, new { Email = model.Email });
WebSecurity.Login(model.UserName, model.Password);
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
I am not trying to use the email address as the login, just want to grab it during the registration step so I can send an auto confirm email.
I have tried with the UserProfile table included in the EF model, and with it out, no difference. I have confirmed the table in the DB has a Email column.
If you're using the default connection, open the database by clicking View -> Server Explorer then expand the DefaultConnection. Under Tables you will see the UserProfile table. Add your columns to the table first and update the database, then add your extra fields to the class.
I'm guessing that the Email property (in your UserProfile class) was somthing you added after you already executed the application for the first time , so if the table already exist befor you changed your model and added the Email property, It might be the cause for the exception.
as you mentioned yourself in one of your comments:
If I remove the section , new{ Email etc ' from the Register method in the controller, it pass fine
To fix that, I think you need to do somthing like that in your DbContext deriven class.(assuming you use code first approach):
public class myDbContext: DbContext
{
public myDbContext()
: base("DefaultConnection")
{
Database.SetInitializer<myDbContext>(new DropCreateDatabaseIfModelChanges<myDbContext>());
}
public DbSet<UserProfile> UserProfiles { get; set; }
}
The default setting is CreateDatabaseIfNotExists ,so if your UserProfile table was already exist, it didn't create it again and didn't find your new Email property (It was in your model but not in the database table);

How to collect membership, role, and profile data on registration ASP.NET MVC4

What is the best way to collect all relevant information user, role, and profile information on the registration page. My current approach is to set additional fields in the register model:
public class RegisterModel
{
[Required]
[Display(Name = "Email")]
[DataType(DataType.EmailAddress)]
public string UserName { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
[Required]
[Display(Name = "Account type")]
public string Role { get; set; }
}
See Role as the last item. I plan to add profile information here as well.
Then in my controller I do this.
public ActionResult Register(RegisterModel model)...
WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
WebSecurity.Login(model.UserName, model.Password);
Roles.AddUserToRole(model.UserName, model.Role);
Is this ok to pass these additional data elements even though they are not part of the UserProfile class? What I am doing works but it just seems wrong.