Search code examples
asp.netrazorrazor-pages

Return page but leave input


I am creating a simple login form. upon button click this function is fired:

public async Task<IActionResult> OnPostButton_Login(IFormCollection data)
{
    var emailAddress = Request.Form["emailaddress"];     
    var pass = Request.Form["password"];

    if (String.IsNullOrEmpty(emailAddress)) return Page();
    if (String.IsNullOrEmpty(pass)) return Page();

    await GetUser(emailAddress , pass);

    return Page();
}

If the user doesn't type anything under either email or password, the page reloads - but also clears all inputs.

How can I return from this function but leave everything untouched (and just return an alert?)


Solution

  • How can I return from this function but leave everything untouched (and just return an alert?)

    Add the [BindProperty] attribute to the properties you want to reload into the returned page.

    [BindProperty]
    public string emailaddress { get; set; }
    
    [BindProperty]
    public string password { get; set; }
    

    Use the ModelState.AddModelError method to add a string alert/message to the returned page.

    ModelState.AddModelError(string.Empty, "My message: Please provide an email address.");
    

    Here's a stripped down version of a login page using your code:

    Login.cshtml.cs

    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.RazorPages;
    
    namespace WebApplication1.Areas.Identity.Pages.Account
    {
        public class LoginModel : PageModel
        {
        [BindProperty]
        public string emailaddress { get; set; }
    
        [BindProperty]
        public string password { get; set; }
    
            public async Task OnGetAsync(string returnUrl = null)
            {
                await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
            }
    
            public async Task<IActionResult> OnPostButton_Login(IFormCollection data)
            {
                string emailAddress = Request.Form["emailaddress"].ToString();
                string pass = Request.Form["password"].ToString();
    
                if (String.IsNullOrEmpty(emailAddress))
                {
                    ModelState.AddModelError(string.Empty, "My message: Please provide an email address.");
                    return Page();
                }
                if (String.IsNullOrEmpty(pass))
                {
                    ModelState.AddModelError(string.Empty, "My message: Please provide a password.");
                    return Page();
                }
    
                await GetUser(emailAddress, pass);
    
                return Page();
            }
    
            private Task GetUser(string emailAddress, string pass)
            {
                throw new NotImplementedException();
            }
        }
    }
    

    Login.cshtml

    @page
    @model LoginModel
    @{
        ViewData["Title"] = "Log in";
    }
    <h1>@ViewData["Title"]</h1>
    <div class="col-md-4">
        <section>
            <form id="account" method="post">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <div class="form-floating">
                    <input asp-for="emailaddress" class="form-control" autocomplete="username" aria-required="true" />
                    <label asp-for="emailaddress" class="form-label"></label>
                    <span asp-validation-for="emailaddress" class="text-danger"></span>
                </div>
                <div class="form-floating">
                    <input asp-for="password" class="form-control" autocomplete="current-password" aria-required="true" />
                    <label asp-for="password" class="form-label"></label>
                    <span asp-validation-for="password" class="text-danger"></span>
                </div>
                <div>
                    <input type="submit" value="Submit" asp-page-handler="Button_Login" />
                </div>
            </form>
        </section>
    </div>
    

    enter image description here

    Alternative, manual control of the submit process

    Here's a full list of what can be returned by a post method in a Razor page. You can take control of the submit process through JavaScript on the client and using the fetch API.

    You can post to the OnPostButton_Login and then return with a content result (e.g. return Content("This is a message."); to the Promise callback of the fetch method. In this process, your page does not reload but just the input values in the form are posted. Here's a SO post of controlling the submit process.