My login and register forms are on the same page.
In ASP.NET Core Razor Pages, I have a page called account
, in which there are two handlers, one is OnPostLogin
for login and OnPostRegister
for new user registration.
I defined two properties at the class level, loginModel
and registerModel
, so that I can connect the form inputs to each property with tag helper. In the asp-page-handler
, I put each form for its own handler. When I want to do validation in the code, I use this code:
if (ModelState.IsValid)
It is never valid and is always invalid because of other form entries, that is, the login entries are not valid for registration (because they are empty) and the register form entries are not valid for login either.
How do I solve the problem?
I guessed that:
if (ModelState.IsValid)
{
// Register Or Login Action
}
I deleted it from my code and performed validation on the client side with jQuery validation, but I have to do this on the server side as well.
You can separate the login and register forms into two different partial views. This way, each form will have its own isolated scope and validation context.
Here's my working demo based on this PageModel:
public class RegisterOrLoginModel : PageModel
{
public class RegisterModel
{
[Required]
public string UserName { get; set; }
[Required]
public string Password { get; set; }
}
public class LoginModel
{
[Required]
public string UserName { get; set; }
[Required]
public string Password { get; set; }
}
}
Here's are the partials showing how to pass the relevant class to its @model
directive:
_RegisterPartial.cshtml
@model RegisterOrLoginModel.RegisterModel
<h4>Register</h4>
<form method="post" asp-page-handler="Register">
<input asp-for="UserName" /><br />
<input asp-for="Password" /><br />
<button>Submit</button>
</form>
_LoginPartial.cshtml
@model RegisterOrLoginModel.LoginModel
<h4>Log In</h4>
<form method="post" asp-page-handler="Login">
<input asp-for="UserName" /><br />
<input asp-for="Password" /><br />
<button>Submit</button>
</form>
Include both partial in the Razor page like this:
<partial name="_LoginPartial" model="new RegisterOrLoginModel.LoginModel()" />
<partial name="_RegisterPartial" model="new RegisterOrLoginModel.RegisterModel()" />
Then, instead of having two bound properties in your PageModel, update your handlers to take the respective model as a parameter. Then ModelState
will only work with the parameter and will not be affected by other stuff:
public void OnPostRegister(RegisterModel model)
{
if(ModelState.IsValid)
{
// ...
}
}
public void OnPostLogin(LoginModel model)
{
if (ModelState.IsValid)
{
// ...
}
}
Alternatively, create separate pages for each form.