Asp.net core razor pages BindProperty collections List not Working

Ashkan 121 Reputation points
2024-07-18T12:03:11.6733333+00:00

My plan is that I fill a list of data in OnGet and after sending it to the html page, I check some lines and fill some input on table and finally it is posted to the server. But in OnPost, the collection is empty and does not return anything:

public class PermDateCourseViewModel
 {
     public string ClassDateS { get; set; }
     public DateTime ClassDate { get; set; }
     public string Weekday { get; set; }
     public string ClassTime { get; set; }
     public bool IsChecked { get; set; }

 }

public class CourseSessionsSetModel : PageModel
 {
     [BindProperty]
     public List<PermDateCourseViewModel> PermDates { get; set; }


     [TempData]
     public string ShowMessage { get; set; }

     private readonly DbkabirContext db;
     public CourseSessionsSetModel(DbkabirContext context)
     {
         db = context;
     }

     public void OnGet(int Id)

     {

         DateTime StartPeriod = DateTime.Now;
       
         PermDates = new List<PermDateCourseViewModel>();
       
       
                 PermDateCourseViewModel permDate = new PermDateCourseViewModel()
                 {
                     ClassDate = StartPeriod,
                     ClassDateS = StartPeriod.ToString().ToShamsi(),
                     Weekday = PersianShamsi.ReturnWeekDayname(StartPeriod.ToString().ToShamsi()),
                     ClassTime = "08:00",
                     IsChecked = true,
                 };


     }
     public IActionResult OnPostAddSession(int CurCourseId)
     {
         for (int i = 0; i < PermDates.Count; i++)
         {
              //process on permDates
         }
         return null;
     }

 }


@page
@model KabirLang.Pages.CourseSessionsSetModel
@{

}

<div class="col-md-12">
        <form method="post">
            <div class="row">
                
                <div class="col-lg-6">
                    <div class="portlet box bg-light m-5">
                        <div class="portlet-body">
                            <table class="table compact">
                                <thead>
                                    <tr>
                                        <td>انتخاب</td>
                                        <td>روز</td>
                                        <td>تاریخ</td>
                                        <td>ساعت</td>
                                    </tr>
                                </thead>
                                <tbody>
                                    @foreach (var item in Model.PermDates)
                                    {
                                        <tr>
                                            <td>
                                                <input type="checkbox" @item.IsChecked />
                                            </td>
                                            <td>@item.Weekday</td>
                                            <td>@item.ClassDateS</td>
                                            <td>
                                                <input class="form-control clockpicker-autoclose" asp-for="@item.ClassTime" />
                                            </td>
                                        </tr>
                                    }
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>

                <div class="col-lg-2">
                    <div class="m-5">
                        <button type="submit" asp-page-handler="AddSession" class="btn btn-info btn-block btn-success m-5">
                            <i class=" fas fa-chevron-left"></i>

                        </button>

                        <button type="submit" asp-page-handler="DelSession" class="btn btn-info btn-block btn-danger m-5">
                            <i class="icon-close"></i>
                        </button>
                    </div>
                </div>

            </div>
        </form>
/div>

Untitled

Please guide me, what changes should I make in the codes, to receive the collection Data in OnPostAddSession Handler along with the changes made by the user in the inputs on the client side?

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,597 questions
0 comments No comments
{count} votes

Accepted answer
  1. AgaveJoe 28,536 Reputation points
    2024-07-18T12:30:01.4333333+00:00

    The model binder expects input names to contain an index otherwise the model binder does not know the incoming data is a collection. Use a for...loop not a foreach as illustrated in the following reference.

    https://www.learnrazorpages.com/razor-pages/model-binding#binding-simple-collections

    There are several other issues. The checkbox inputs do not have a name so the browser will not submit the checkboxes. The model has five properties but the HTML form has one input with a name; ClassTime.

    I think it would be helpful if you went through the tutorials in this site to learn the basic Razor Pages patterns. Step 7 in the following tutorial illustrates how to handle a checkbox collection.

    https://learn.microsoft.com/en-us/aspnet/core/data/ef-rp/update-related-data?view=aspnetcore-8.0

    I recommend starting from the beginning.

    https://learn.microsoft.com/en-us/aspnet/core/data/ef-rp/intro?view=aspnetcore-8.0&tabs=visual-studio


1 additional answer

Sort by: Most helpful
  1. Inayat Ali 0 Reputation points
    2024-07-18T12:33:27.42+00:00

    It sounds like you are trying to use ASP.NET Core's Razor Pages to handle a form that populates data on the OnGet method, displays it in a view, allows the user to interact with it, and then processes the form data in the OnPost method. However, the issue is that the data collection is not being retained or passed correctly to the OnPost method. Here's how you can address this issue:

    1. Ensure you are using the correct binding attributes: Use [BindProperty] to bind the form data to a property in your Razor Page model.

    2. Preserve data between requests: If the data needs to be preserved between the OnGet and OnPost methods, consider using hidden fields or session state.

    3. Properly binding collections: Ensure that the collection is properly bound to the form inputs.

    Here's an example of how you might set this up:

    Page Model (Razor Page Model)

    
    using Microsoft.AspNetCore.Mvc;
    
    using Microsoft.AspNetCore.Mvc.RazorPages;
    
    using System.Collections.Generic;
    
    namespace YourNamespace.Pages
    
    {
    
        public class YourPageModel : PageModel
    
        {
    
            [BindProperty]
    
            public List<YourDataModel> DataList { get; set; }
    
            public void OnGet()
    
            {
    
                // Initialize the list with some data
    
                DataList = new List<YourDataModel>
    
                {
    
                    new YourDataModel { Id = 1, Name = "Item 1" },
    
                    new YourDataModel { Id = 2, Name = "Item 2" }
    
                };
    
            }
    
            public IActionResult OnPost()
    
            {
    
                // DataList should now be populated with the form data
    
                if (ModelState.IsValid)
    
                {
    
                    // Process the data
    
                }
    
                // Return to the page or redirect as necessary
    
                return Page();
    
            }
    
        }
    
        public class YourDataModel
    
        {
    
            public int Id { get; set; }
    
            public string Name { get; set; }
    
        }
    
    }
    
    

    Razor Page (HTML)

    
    @page
    
    @model YourNamespace.Pages.YourPageModel
    
    @{
    
        ViewData["Title"] = "Your Page";
    
    }
    
    <h1>Your Page</h1>
    
    <form method="post">
    
        <table>
    
            <thead>
    
                <tr>
    
                    <th>ID</th>
    
                    <th>Name</th>
    
                </tr>
    
            </thead>
    
            <tbody>
    
                @for (int i = 0; i < Model.DataList.Count; i++)
    
                {
    
                    <tr>
    
                        <td>
    
                            <input type="hidden" asp-for="DataList[i].Id" />
    
                            @Model.DataList[i].Id
    
                        </td>
    
                        <td>
    
                            <input asp-for="DataList[i].Name" />
    
                        </td>
    
                    </tr>
    
                }
    
            </tbody>
    
        </table>
    
        <button type="submit">Submit</button>
    
    </form>
    
    @section Scripts {
    
        <partial name="_ValidationScriptsPartial" />
    
    }
    
    

    Explanation

    • OnGet Method**: This method initializes the DataList with some sample data. This data is then rendered in the HTML form.

    - OnPost Method: When the form is submitted, the OnPost method is called. The DataList property is populated with the form data due to the [BindProperty] attribute.

    - Form Binding: The HTML form uses asp-for to bind the form fields to the DataList property. The for loop ensures that each item in the DataList is rendered as a row in the table.

    - Hidden Fields: Hidden input fields are used to retain the Id values between the OnGet and OnPost requests.

    Ensure that the names of the input fields match the structure of the model properties to enable correct binding.

    This should allow you to populate the data on the OnGet method, interact with it on the HTML page, and then have the modified data posted back to the server correctly on the OnPost method.

    You can also view our product paying guest management software


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.