3

I have simple login form.
Everything works great except one thing. When you enter the page it always shows validation (eg. fields are required), even when no data was POSTed to the controller.
Is there any way to show validation only when there is actually POST request made?

View:

@model LoginViewModel
<form asp-controller="User" asp-action="Login" method="post">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>

    <label asp-for="Email"></label>
    <input asp-for="Email" />
    <span asp-validation-for="Email"></span>

    <label asp-for="Password"></label>
    <input asp-for="Password" />
    <span asp-validation-for="Password"></span>

    <button type="submit">Login</button>
</form>

ViewModel:

public class LoginViewModel
{
    [Required]
    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }
    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }
}

Action:

[HttpGet]
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login(LoginViewModel model)
    {
        ClaimsPrincipal userClaims = _userRepository.TryLogin(model);

        if (userClaims != null)
        {
            ...
        }
        return View(model);
    }
m.cichacz
  • 749
  • 9
  • 21
  • [this SO question should be of interest](http://stackoverflow.com/q/20642328/463206) .... [and this SO question](http://stackoverflow.com/q/7390902/463206) – radarbob Jan 13 '17 at 22:38
  • 3
    try to take out the `[HttpGet]` from the Login function. – Paul Karam Jan 13 '17 at 22:42

1 Answers1

4

As Paul alluded to in the comments, you should remove the [Get] attribute which will prevent Get requests to the action and instead, create a new controller action responsible for handling get requests that doesn't result in the action's model LoginViewModel being null.

For instance:

[AllowAnonymous]
public async Task<IActionResult> Login()
{
    return View(new LoginViewModel());
}

[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login(LoginViewModel model)
{
    ClaimsPrincipal userClaims = _userRepository.TryLogin(model);

    if (userClaims != null)
    {
        ...
    }
    return View(model);
}

Now your validation will only trigger as a result of an invalid post model.

Joseph Woodward
  • 9,191
  • 5
  • 44
  • 63
  • Thanks! That did the trick. I wanted to keep it in one action, but this approach at least works :) – m.cichacz Jan 14 '17 at 14:18
  • Glad it helped. Separating commands from queries (post from get) can often make things more maintainable. Not to mention having the one method handle both post and get would violate the single responsibility principle. – Joseph Woodward Jan 14 '17 at 19:40