Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.Net Core Razor Pages dynamic list

Tags:

c#

razor-pages

I want to create a website with Razor pages to maintain spaces and the according rooms. So, in my model a space has a list of rooms.

public class Space
{
    public int Id { get; set; }
    public string SpaceName { get; set; }
    public List<Room> Rooms { get; set; }

    public Space()
    {
        this.Rooms = new List<Room>();
    }
}

In the create.cshtml I want to dynamically add and remove rooms

<h1>Create New Space</h1>
<form method="post">
    <div class="form-group">
       <label for="Space.SpaceName">Space Name</label>
       <input type="text" class="form-control" asp-for="Space.SpaceName" placeholder="Enter space name">
       <span asp-validation-for="Space.SpaceName" ></span>
    </div>
    @if(Model.Space != null){
        for (int i = 0; i < Model.Space.Rooms.Count; i++)
        {
         <input asp-for="@i" type="hidden" />
         <div class="form-group">
             <label for="SpaceName">Room Name</label>
             <input type="text" class="form-control" asp-for="Space.Rooms[i].Name" placeholder="Enter space name">
             <span asp-validation-for="Space.Rooms[i].Name" ></span>
         </div>

         <button type="submit" asp-page-handler="removeroom" asp-route-index="@i">Remove Room</button>
         }
    }

    <button type="submit" asp-page-handler="addroom">Add Room</button>

    <button type="submit" asp-page-handler="submit" class="btn btn-primary">Submit</button>
</form>

The PageModel looks like this:

public class CreateModel : PageModel
{
    readonly SpaceRepository spaceRepository;

    public CreateModel(SpaceRepository spaceRepository)
    {
        this.spaceRepository = spaceRepository;
    }

    [BindProperty]
    public Space Space { get; set; }

    public async Task<IActionResult> OnPostSubmitAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        spaceRepository.Create(Space);
        return RedirectToPage("./Index");
    }

    public async Task OnPostAddRoomAsync()
    {
        Space.Rooms.Add(new Room());
    }

    public async Task OnPostRemoveRoomAsync(int index)
    {
        Space.Rooms.RemoveAt(index);
    }
}

So far it works as expected, but when I create for example 3 rooms and delete the first or second one, it always deletes the last one.

The page seems not to receive the manipulated list after the handler post.

Any ideas what's missing?

Thank you for your help!

like image 628
El Stefano Avatar asked Nov 08 '22 07:11

El Stefano


1 Answers

I know you probably don't need it anymore, but I also had a problem with that so I opened an issue on github and I got an answer for your question: https://github.com/aspnet/Mvc/issues/8373
So basically MVC is round tripping model, so the fields can remain filled. Because of that, page model uses last known modelstate to fill every field. You can fix that by using Modelstate.Clear() after you delete your item. Thanks to that you will also not show any validation message after just deleting item from list.

like image 122
Krystian Kolad Avatar answered Nov 11 '22 15:11

Krystian Kolad