Search code examples
asp.netasp.net-corerazor

Keep the form data when validation fails


I am trying to validate input in an ASP.NET razor pages project.

How can I keep the form data when my model validation fails?

When my model validation fails, both the select fields and the list of items to choose from are empty.

<div class="row">
    <div class="col-md-4">
        <form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Loan.Book" class="control-label"></label>
                <select asp-for="Loan.BookID" class ="form-control" asp-items="ViewBag.Books"></select>
            </div>
            <div class="form-group">
                <label asp-for="Loan.Reader" class="control-label"></label>
                <select asp-for="Loan.ReaderID" class="form-control" asp-items="ViewBag.Readers"></select>
            </div>
            <div class="form-group">
                <label asp-for="Loan.DueDate" class="control-label"></label>
                <input asp-for="Loan.DueDate" class="form-control" />
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

C# Code

public IActionResult OnGet()
{
    ViewData["Books"] = new SelectList(_context.Book, "ID", "Title");
    ViewData["Readers"] = new SelectList(_context.Reader, "ID", "Name");
    return Page();
}

[BindProperty]
public Loan Loan { get; set; } = default!;


// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid || _context.Loan == null || Loan == null)
    {
        return Page();
    }

    Book book = await _context.Book.FindAsync(Loan.BookID);

    if (book.InStock <= 0)
    {
        ModelState.AddModelError("Loan.Book", "This book is out of stock");
        return Page();
    }

    book.InStock--;

    _context.Loan.Add(Loan);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

Empty select secreenshot:

enter image description here


Solution

  • To keep the list of items to choose from are not empty, you need to add below code in your OnPostAsync() :

    ViewData["Books"] = new SelectList(_context.Book, "ID", "Title",Loan.BookID);
    ViewData["Readers"] = new SelectList(_context.Reader, "ID", "Name",Loan.ReaderID);