Use email address instead of username with ASP.NET Forms authentication - asp.net-mvc

I'm starting a brand new ASP.NET MVC application using the built in "Internet application" template.
How can I set it up to allow login using email address & password instead of username & password?

If you're using the default AccountModels you might as well change the LogOnModel to remove UserName and add Email, like this:
public class LogOnModel {
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
Change occurrences of UserName to Email in your LogOn view as well.
Finally in your AccountController, change the LogOn action to get the UserName from the email address to complete the SignIn process, like this:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl) {
if (ModelState.IsValid) {
var userName = Membership.GetUserNameByEmail(model.Email);
if (MembershipService.ValidateUser(userName, model.Password)) {
FormsService.SignIn(userName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl)) {
return Redirect(returnUrl);
} else {
return RedirectToAction("Index", "Home");
}
} else {
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}

we have same requirement and do this,
you should create custom identity (CustomIdentity : IIdentity, ISerializable)
[Serializable]
public class CustomIdentity : IIdentity, ISerializable
and define Name property for it.
then for get method of name property return email of user
public string Name
{
get{ return Email; }
}
if detail be needed, please comment on this post

Isn't the solution as simple as using the name field as an email address?

Related

MVC: Custom login page uses same field validators as Register page incorrectly

New to MVC. Using Entity Framework and database first.
Problem
-Register page has fields for username, password, confirm password, and e-mail with validators.
-Login page has username and password fields also with validators. Login page asks for confirm password and e-mail when it shouldn't.
Goal
-Fix this, and maybe learn some proper way of using models in the meantime. I have read many articles and seen many videos but a lot use code first, which I am not using. Very confusing to me.
CODE
My User database doesn't have a Confirm Password field so I made a model...
namespace StoreFront.Models
{
[MetadataType(typeof(RegisterViewModel))]
public partial class User
{
[DataType(DataType.Password)]
public string ConfirmPassword { get; set; }
}
}
My CustomerBaseViewModel has the LoginViewModel and RegisterViewModel that my views should be using...
public class LoginViewModel
{
public int UserID { get; set; }
[DisplayName("Username")]
[Required(ErrorMessage = "Username is required")]
public string UserName { get; set; }
[DisplayName("Password")]
[DataType(DataType.Password)]
[Required(ErrorMessage = "Password is required")]
public string Password { get; set; }
}
public class RegisterViewModel
{
public int UserID { get; set; }
[DisplayName("Username")]
[Required(ErrorMessage = "Username is required")]
public string UserName { get; set; }
[DisplayName("Password")]
[DataType(DataType.Password)]
[Required(ErrorMessage = "Password is required")]
public string Password { get; set; }
[DisplayName("Confirm Password")]
[DataType(DataType.Password)]
[Compare("Password", ErrorMessage = "Passwords must match")]
public string ConfirmPassword { get; set; }
[DisplayName("Email")]
[Required(ErrorMessage = "Email is required")]
[RegularExpression(#"^([a-zA-Z0-9_\-\.]+)#([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$",
ErrorMessage = "Please enter a valid email")]
public string EmailAddress { get; set; }
}
I have two separate controllers...one for login and one for register. Not sure if you need to look at it but I added anyway
public class LoginController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(User user)
{
using (StoreFrontContext db = new StoreFrontContext())
{
if (!ModelState.IsValid)
{
return View();
}
else
{
var usr = db.Users.Where(u => u.UserName.ToLower() == user.UserName.ToLower() && u.Password == user.Password).FirstOrDefault();
if (usr != null)
{
Session["Username"] = usr.UserName.ToString();
Session["UserID"] = usr.UserName.ToString();
}
else
{
ModelState.AddModelError("", "Username or Password is incorrect.");
}
}
}
return View();
}
}
public class RegisterController : Controller
{
StoreFrontContext db = new StoreFrontContext();
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(User account)
{
if (ModelState.IsValid)
{
using (db)
{
bool duplicate = true;
foreach (var name in db.Users)
{
if (account.UserName.ToLower() == name.UserName.ToString().ToLower())
{
ModelState.AddModelError("", "Username already exists in database!");
duplicate = true;
break;
}
else
{
duplicate = false;
}
}
if (!duplicate)
{
account.IsAdmin = false;
account.DateCreated = DateTime.Now;
db.Users.Add(account);
db.SaveChanges();
ModelState.Clear();
}
}
}
return View();
}
}
Login Index() View uses #model StoreFront.Models.LoginViewModel and Register Index() View uses #model StoreFront.Models.RegisterViewModel
I can't seem to figure out what is wrong, but I believe it's what is being passed through the View or the controller. I'm still not very familiar with the Model part of MVC yet..been very struggling on that, so any pointers on that would also help. Any help would be strongly appreciated!!

Log-out operation in MVC

I've created my login using simple session element. I need a logout process as simple as i did. How can i create Log-out in harmony with my Log-in codes? Thanks in advance.
Here is my model below;
public class LoginModel
{
public string UserName { get; set; }
public string Password { get; set; }
public string ErrorMessage { get; set; }
}
and also my controller is below;
public ActionResult Index()
{
Session["User"] = null;
LoginModel model = new LoginModel();
return View(model);
}
[HttpPost]
public ActionResult Index(LoginModel data)
{
string user = System.Configuration.ConfigurationManager.AppSettings["UserName"];
string password = System.Configuration.ConfigurationManager.AppSettings["Password"];
if (data.UserName == user && data.Password == password)
{
Session["User"] = "1";
return RedirectToAction("Index", "Home");
}
else
{
data.ErrorMessage = "Incorrect password or username entered. Please try again.";
return View(data);
}
}
If your definition of "the user is logged in" is "The UserID is stored in Session["User"]", then logging out is equally trivial: just clear the session variable, as explained in ASP.NET removing an item from Session?:
[HttpPost]
public ActionResult LogOut()
{
Session.Remove("User");
}

ModelState.IsValid is true if password is empty string

I am passing login model to mvc4 default login method
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && _webSecurity.login(model))
{
return RedirectToLocal(returnUrl);
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
My Model looks like following
var _loginModel = new LoginModel
{
UserName = abc#gmail.com,
Password = ""
};
but ModelState.IsValid is returning true . I don't know why . Help me
Thanks in advance .
Edit
Here is my LoginModel
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; }
}
The validation Attribute defined in the model will be apllied while Model Binding, u don't have to do this manualy.
[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; }
For more complex validation you also could add a regex filter like this:
[RegularExpression(#"^[^\<\>]*$", ErrorMessage = "May not contain <,>")]
This would match windows group policy password filter for example:
(?=^.{6,255}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*

How to input data to custom column in userprofile table when creating a new user

I have added a custom column to my user profile table that is called CoID (int).
When I want to create a new user I want to send the value 1 to CoID, but I am experiencing some trouble and cant get it to work properly.
I am using the standard account tables from mvc4.
Here are some of my code
AccountModel.cs
public class RegisterModel
{
[Required]
[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; }
[DataType(DataType.Custom)]
[Display(Name = "CoID")]
[Compare("CoID", ErrorMessage = "plese insert CoID")]
public int CoID { get; set; }
}
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public int CoID { get; set; }
}
AccountController.cs
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
model.CoID = 1;
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password, model.CoID);
WebSecurity.Login(model.UserName, model.Password);
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
When executing this code i am getting this error:
The custom Data-type string cannot be null or empty.
I think your call to WebSecurity.CreateUserAndAccount might need looking at.
Perhaps the following might work better:
WebSecurity.CreateUserAndAccount(model.UserName, model.Password,
new { CoID = model.CoID });
As from the anonymous object it can work out what values you're trying to assign to what field names. Otherwise you're just passing through the value and it doesn't know where to put it.
Remove [DataType(DataType.Custom)] or change to [DataType("CoID")].

asp.net mvc: how to extend account controller?

I have a asp.net mvc application that uses standard account controller to handle auth.
The client asked me to add new fields as email, city, age to account creation.
Which would be the best way to extend account controller/model?
Should i modify aspnet_users table or should i create a new table with the new fields? Is it a right way to add new fields to AccountFormViewModel?
I guess you have two option:
1) Creating your custom membership provider.
2) Using the builtin profile membership provider
Anyway you have to implement/extend the AccountController and ViewModel that you get with a new MVC project.
If you choose the first option you can add your fields to the aspenet_users table.
If you choose the second option you use the profile table that the framework want you to create.
If you want a "super integration" of your fields you can consider to extend the IIdentity and IPrincipal interfaces. Look at this answer for some more info.
Hope it helps
First you have modify the RegisterModel AcountModels, and add new fileds
public class RegisterModel
{
[Required]
[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; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
in AcountController you modify the Register action
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
try
{
WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
WebSecurity.Login(model.UserName, model.Password);
using (var context = new ECDB())
{
var username = model.UserName;
var user = context.UserProfiles.SingleOrDefault(u => u.UserName == username);
user.FirstName = model.FirstName;
user.LastName = model.LastName;
user.Email = model.Email;
context.SaveChanges();
}
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException e)
{
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}

Resources