我知道,如果我有不同的登录和注册视图模型,这会更容易,但不幸的是,它们必须在同一个视图模型中。这是用户控制器中的相关方法
public async Task<IActionResult> Login([Bind("Email,Password")]UserViewModel m)
{
// call service to Authenticate User
var user = svc.Authenticate(m.Email, m.Password);
if (user == null)
{
ModelState.AddModelError("Email", "Invalid Login Credentials");
ModelState.AddModelError("Password", "Invalid Login Credentials");
return View(m);
}
// sign user in using cookie authentication to store principal
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
BuildClaimsPrincipal(user)
);
return RedirectToAction("Index","Home");
}
public IActionResult Register()
{
return View();
}
[HttpPost]
// add validate anti forgery token
[ValidateAntiForgeryToken]
public IActionResult Register([Bind("Name, Email, Password, PasswordConfirm, Role")]UserViewModel m)
{
// Q2
// attempt to retrieve a user by the viewmodel email address (call svc.GetUserByEmail(m.Email))
// var user = svc.GetUserByEmail(m.Email);
// // if user returned is not null then
// if(user != null)
// // add a modelstate error as email address must already be in use
// // see login action above for example of adding manual modelstate error
// {
// ModelState.AddModelError("Email", "Email Address Already In Use");
// return View(m);
// }
// endif
// if not valid model
if(!ModelState.IsValid)
{
return View(m);
}
// call service to register user
// Add alert indicating registration successful and redirect to login page
svc.Register(m.Name, m.Email, m.Password, m.Role);
Alert("Registration Successful", AlertType.info);
return RedirectToAction(nameof(Login));
}
[HttpPost]
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction(nameof(Login));
}
[AcceptVerbs("GET","POST")]
public IActionResult VerifyEmail(string email)
{
if (svc.GetUserByEmail(email) != null)
{
return Json($"Email {email} is already in use.");
}
return Json(true);
}
这是用户视图模型
public class UserViewModel
{
// Q3 add validation attributes
[Required]
public string Name { get; set; }
[Required]
[EmailAddress]
[Remote(action: "VerifyEmail", controller: "User")]
public string Email { get; set; }
[Required]
public string Password { get; set; }
[Compare("Password", ErrorMessage = "Confirm Password doesn't match! Try again!")]
public string PasswordConfirm { get; set; }
[Display(Name = "Role")]
[Required(ErrorMessage = "{0} is required.")]
public Role Role { get; set; }
}
所以当我注册时,如果电子邮件正在使用,它会显示一个错误,这很好!但是,在登录页面上,它说电子邮件已经在使用,不允许任何人登录?有人能在保持模型不变的同时找到解决方案吗?
您可以使用请求对象引用标头。在VerifyEmail方法的开头添加以下行:
var referer = Request.Headers["Referer"];
if (referer.Count > 0 && referer.ToString().Contains("Login"))
{
return Json(true);
}
我们正在检查标头中的传入请求源页面,如果它存在并且是从登录页面启动的,我们将不再继续。