简体   繁体   English

在 .netCore Razor 页面上挣扎于数据绑定模型

[英]Struggling with Data Binding Model on post .netCore Razor Pages

I'm currently struggling with getting data to bind on a post event.我目前正在努力获取要绑定到 post 事件的数据。

I'm Using EF core to load data to object which use to load and display the list of data.我正在使用 EF 核心将数据加载到用于加载和显示数据列表的对象。

  <div class="container">
    <form method="post">
        @if (Model.HeadersHasData)
        {
           // unnessary codes 


            @foreach (var item in Model.DisplayDataHeaders)
            {
                <div class="container mb-2">
                    <div class="row border-dark border-top">
                        <div class="col-sm-1">@Html.DisplayFor(c => item.ServiceAbbr)</div>
                        <div class="col-sm-4">@Html.DisplayFor(c => item.ServiceName)</div>
                        <div class="col-sm-3">@Html.DisplayFor(c => item.Qty) Hours/IPs/Locations</div>
                        <div class="col-sm-2">@Html.DisplayFor(c => item.Description) Duration</div>
                    </div>
                    @if (Model.DetailsHasData)
                    {
                        @foreach (var details in Model.DisplayDataDetails)
                        {
                            @if (details.ServiceId == item.ServicesId)
                            {
                                <div class="row">
                                    <input type="hidden"
                                           name="DisplayDataDetails.Index"
                                           value="@details.TaskAssignedId" />
                                    <input type="hidden"
                                           name="DisplayDataDetails[@details.TaskAssignedId].TaskAssignedId"
                                           value="@details.TaskAssignedId" />
                                    <div class="col-sm-1">
                                        <input type="checkbox"
                                               name="DisplayDataDetails[@details.TaskAssignedId].TaskComplete"
                                               value="@details.TaskComplete"
                                               checked=@details.TaskComplete
                                               disabled="@details.AccessGranted" />
                                    </div>
                                    <div class="col-sm-2">@details.TaskName</div>
                                    <div class="col-sm-1">@details.TaskStartDate.ToShortDateString()</div>
                                    <div class="col-sm-1">@details.TaskEndDate.ToShortDateString()</div>
                                    <div class="col-sm-2">@details.TechLead</div>
                                    <div class="col-sm-2">@details.Tech2</div>
                                    <div class="col-sm">@details.Tech3</div>
                                </div>
                            }
                        }
                    }
                </div>
            }

        }
        <button type="submit">Test</button>
    </form>
</div>

This displays the data and everything correctly.这将正确显示数据和所有内容。

I'm now working on the interaction for when user change the check-boxes (will eventual try to figure on change event for check-boxes) current useing .我现在正在研究当前使用 .

I've applied [bindProperty] but every-time a debug through DisplayDataDetails object I get an object with a count of 13 which is the correct number of rows expected but all rows are null.我已经应用了 [bindProperty] 但每次通过 DisplayDataDetails 对象进行调试时,我都会得到一个计数为 13 的对象,这是预期的正确行数,但所有行都为空。

I'm very confused on what I'm missing because everything I've read on https://www.learnrazorpages.com/razor-pages/forms/checkboxes and https://www.learnrazorpages.com/razor-pages/model-binding我对自己缺少的东西感到非常困惑,因为我在https://www.learnrazorpages.com/razor-pages/forms/checkboxeshttps://www.learnrazorpages.com/razor-pages/上阅读的所有内容模型绑定

shows this should be a very straight forward action.表明这应该是一个非常直接的操作。

     [BindProperty]
        public List<Detail> DisplayDataDetails { get; set; }

  public async Task OnPostAsync(int? saleId)
        {
            var test = DisplayDataDetails;
            //await LoadDataAsync(saleId);

            var pause= "pause";

        }

Any assistants or suggestion will be appreciated.任何助手或建议将不胜感激。

Update 1更新 1

Just Wanted to add and update,created a separate test project and was able to walk through the Binding Complex Collections example in the https://www.learnrazorpages.com/razor-pages/model-binding I modified the view to match my use case and was able to get data back even with checkboxes values on post back with data-binding.只是想添加和更新,创建了一个单独的测试项目,并能够通过https://www.learnrazorpages.com/razor-pages/model-binding 中的绑定复杂集合示例我修改了视图以匹配我的使用case 并且即使在使用数据绑定回发时使用复选框值也能够取回数据。

this works .cs这有效.cs

namespace RazorPages
{
    public class ModeContactTestModel : PageModel
    {
        [BindProperty]
        public List<Contact> Contacts { get; set; } = new List<Contact>();
        public string stubFirstName { get; private set; }
        public string stubLastName { get; private set; }

        public void OnGet()
        {
           LoadTestData();
        }

        private void LoadTestData()
        {
            //Contacts = 
            stubFirstName = "john";
            stubLastName = "Doe";
            for (var i = 0; i < 5; i++)
            {
                Contacts.Add(new Contact
                {
                    ContactId = i,
                    FirstName = stubFirstName,
                    LastName = stubLastName,
                    Email = stubFirstName + "." + stubLastName + i + "Test@email.com",
                    Enabled =  (i % 2 == 0) ?  true : false
                });
            }

        }

        public void OnPost()
        {
            // process the contacts
        }
    }

    public class Contact
    {
        public int ContactId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public bool Enabled { get; set; }
    }
}

.cshtml .cshtml

@page
@model RazorPages.ModeContactTestModel
@{
    ViewData["Title"] = "ModelContactTest";
}

<h1>ModelContactTest</h1>
<form method="post">
    <table class="table">

        <tr>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Email</th>
            <th>Enabled</th>
        </tr>
        @foreach (var contact in Model.Contacts)
        {
            <tr>
                <td>
                    <input type="hidden" name="Contacts.Index" value="@contact.ContactId" />
                    <input type="hidden" name="Contacts[@contact.ContactId].ContactId" value="@contact.ContactId" />
                    @*@contact.ContactId*@
                </td>
                <td><input name="Contacts[@contact.ContactId].FirstName" value="@contact.FirstName" /></td>
                <td><input name="Contacts[@contact.ContactId].LastName" value="@contact.LastName" /></td>
                <td><input name="Contacts[@contact.ContactId].Email" value="@contact.Email" /></td>
                <td>
                    <input type="checkbox" 
                           name="Contacts[@contact.ContactId].Enabled" 
                           value="true" 
                           checked="@contact.Enabled"/></td>
            </tr>
        }
    </table>
    <button>Update</button>
</form>

I create a new demo razorPage to start rewriting my page I started with apples to applies in my working project.... data binding still does not seem to work我创建了一个新的演示 razorPage 开始重写我的页面我从苹果开始应用于我的工作项目......数据绑定似乎仍然不起作用

which is doesn't make any since as I see nothing different that jumps out at me.这是没有任何意义的,因为我没有看到任何不同的东西跳出来。

.cs 。CS

namespace Project.Web.Razor
{
    public class ################: PageModel
    {
        [BindProperty]
        public List<Detail> Details { get; set; }// = new List<Detail>(); //

        public void OnGet()
        {
            LoadData();
        }

        private void LoadData()
        {
            Details = new List<Detail>();
            for (var i = 0; i < 5; i++)
            {
                Details.Add(new Detail
                {
                    AssignedId = i,
                    Name = "Dev Testing Task " + i,
                    Complete = (i % 2 == 0) ? true : false,
                    StartDate = Convert.ToDateTime("01/01/2019"),
                    EndDate = Convert.ToDateTime("01/01/2019"),
                    Lead = "John Doe",
                    //SaleId = i+1,
                    //ServiceId = i + 2,
                    AccessGranted = (i % 2 == 0) ? true : false,

                });
            }
        }

        public void OnPost()
        {
            // process the TaskDetails
        }
    }

    public class Detail
    {
        public int AssignedId { get; internal set; }
        public string  Name { get; internal set; }
        public bool Complete { get; internal set; }
        public DateTime  StartDate { get; internal set; }
        public DateTime  EndDate { get; internal set; }
        public string  Lead { get; internal set; }
        public bool AccessGranted { get; internal set; }
    }
}

.cshtml .cshtml

@page
@model ##########################
@{
    ViewData["Title"] = "#####################";
}

<h1>EngagementingDetails</h1>
<form method="post">
    <table class="table">
        @foreach (var Detail in Model.Details)
        {
            <tr class="row">
                <td>
                    <input type="hidden" name="Details.Index" value="@Detail.AssignedId" />
                    <input type="hidden" name="Details[@Detail.AssignedId].AssignedId" value="@Detail.AssignedId" />
                </td>

                <td class="col">
                    <input type="checkbox" name="Details[@Detail.AssignedId].Complete" value="true" checked="@Detail.Complete" disabled="@Detail.AccessGranted" />
                </td>
                <td class="col">
                    <input type="hidden" name="Details[@Detail.AssignedId].Name" value="@Detail.Name" />
                    @Detail.Name
                </td>
                <td class="col">
                    <input type="hidden"
                           name="Details[@Detail.AssignedId].StartDate"
                           value="@Detail.StartDate" />
                    @Detail.StartDate.ToShortDateString()
                </td>
                <td class="col">
                    <input type="hidden"
                           name="Details[@Detail.AssignedId].EndDate"
                           value="@Detail.EndDate" />
                    @Detail.EndDate.ToShortDateString()
                </td>
                <td class="col">
                    <input type="hidden"
                           name="Details[@Detail.AssignedId].TechLead"
                           value="@Detail.TechLead" />
                    @Detail.TechLead
                </td>

            </tr>
        }
    </table>
    <button>Update</button>
</form>


this is really confusing me why I can get this to work in one project but not anothor it when click update and debug the OnPost event I get returns a list with a count of 5 but each item is null in my working project in the test contract project it returns the list count of 5 with data in each object as expected.这真的让我感到困惑,为什么我可以在一个项目中使用它,但在单击更新和调试 OnPost 事件时却不能让它在另一个项目中工作,我得到返回一个计数为 5 的列表,但测试合同中我的工作项目中的每个项目都为空project 它按预期返回列表计数 5,每个对象中的数据。 Not sure what I'm doing different between the two.不知道我在这两者之间做了什么不同的事情。

Update 2更新 2

In regards to last comment I made the following changes for testing关于最后一条评论,我进行了以下更改以进行测试

.CSHTML .CSHTML

<form method="post">
    <table class="table">
        <tr class="row">
            <th></th>
            <th class="col">Complete</th>
            <th class="col">Name</th>
            @*<th class="col">StartDate</th>
            <th class="col">EndDate</th>
            <th class="col">Lead</th>*@
        </tr>

        @foreach (var detail in Model.Details)
        {
            <tr class="form-group row">
                <td >
                    <input type="hidden" 
                           name="Details.Index" 
                           value="@detail.AssignedId" />
                    <input type="hidden" 
                           name="Details[@detail.AssignedId].AssignedId" 
                           value="@detail.AssignedId" />
                </td>

                <td class="col">
                    <input class="form-check-input"
                           type="checkbox"
                           name="Details[@detail.AssignedId].Complete"
                           value="true"
                           checked="@detail.Complete"
                           />
                </td>
                <td class="col">
                    <input class="form-control form-control-sm"
                           name="Details[@detail.AssignedId].Name" 
                           value="@detail.Name" readonly />                    
                </td>

            </tr>
        }
    </table>
    <button>Update</button>
</form>

.cs 。CS

  [BindProperty]
        public List<Detail> Details { get; set; } = new List<Detail>(); //

        public void OnGet()
        {
            LoadData();
        }

        private void LoadData()
        {
            //Details = new List<Detail>();
            for (var i = 0; i < 5; i++)
            {
                Details.Add(new Detail
                {
                    AssignedId = i,
                    Name = "Dev Testing Task " + i,
                    Complete = (i % 2 == 0) ? true : false,
                    //StartDate = Convert.ToDateTime("01/01/2019").AddDays(i + 1).AddMonths((i)+1),
                    //EndDate = Convert.ToDateTime("01/01/2019").AddDays((i + 1) + 15).AddMonths((i) + 1),
                    //Lead = "John Doe",
                    //SaleId = i+1,
                    //ServiceId = i + 2,
                    //AccessGranted = (i % 2 == 0) ? false : true,

                });
            }
        }

        public void OnPost()
        {
            // process the TaskDetails

            if(Details is null)
            {
                LoadData();
            }else if( Details[0] == null)
            {
                Details = new List<Detail>();
                LoadData();
            }
            else
            {
                Details = new List<Detail>();
                LoadData();
            }



        }
    }

    public class Detail
    {
        public int AssignedId { get; internal set; }
        public string Name { get; internal set; }
        public bool Complete { get; internal set; }
        //public DateTime StartDate { get; internal set; }
        //public DateTime EndDate { get; internal set; }
        //public string Lead { get; internal set; }
        //public bool AccessGranted { get; internal set; }
    }

While debugging I'm still returning onPost List Details back with a count of 5 but each item in it is null.在调试时,我仍然返回 onPost 列表详细信息,计数为 5,但其中的每个项目都为空。 ie. IE。 Details[0] = null, Details 1 = null, etc, etc.详细信息 [0] = 空,详细信息1 = 空等,依此类推。

Just ran fiddler and it seems to be sending the object刚刚跑了提琴手,它似乎正在发送对象

Fidder Output snippet Fidder 输出片段

Now I'm wondering if the bindproperty is failing to pick up the data on the post event.现在我想知道 bindproperty 是否无法在 post 事件中获取数据。

I got it to work我让它工作

I end-up rewriting it completely from scratch using my Contract test as a template.我最终使用我的 Contract 测试作为模板从头开始完全重写它。 Testing the binding after each major change.在每次重大更改后测试绑定。 I added a IndexId column to my object so that I could explicitly set the List index which I believe was my major issue before.我向我的对象添加了一个 IndexId 列,以便我可以明确设置 List 索引,我认为这是我之前的主要问题。 I believe my issue had to do with my two foreach loops I need to to generate the view with out defining an strict index it was causing the binding to fail... that as least what I believe was my issue.我相信我的问题与我需要在没有定义严格索引的情况下生成视图的两个 foreach 循环有关,它导致绑定失败......至少我认为是我的问题。

Fineal CSHTML精细的 CSHTML

        <form method="post">
            @foreach (var row in Model.DetailsHeaders)
            {
                <table class="table table-sm">
                    <thead>
                        <tr>
                            <th colspan="2" scope="colgroup">@Html.DisplayFor(c => row.ServiceAbbr)</th>
                            <th colspan="2" scope="colgroup">@Html.DisplayFor(c => row.ServiceName)</th>
                            <th colspan="2" scope="colgroup">@Html.DisplayFor(c => row.Qty) Hours/IPs/Locations</th>
                            <th colspan="2" scope="colgroup">@Html.DisplayFor(c => row.Description) Duration</th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach (var detail in Model.Details)
                        {
                            if (detail.ServiceId == row.ServicesId)
                            {
                                <tr>
                                    <td scope="row">
                                        <input type="hidden"
                                               name="Details.IndexId"
                                               value="@detail.IndexId" />
                                        <input type="hidden"
                                               name="Details[@detail.IndexId].IndexId"
                                               value="@detail.IndexId" />
                                        <input type="hidden"
                                               name="Details[@detail.IndexId].AssignedId"
                                               value="@detail.AssignedId" />
                                        @*@Html.DisplayFor(r => detail.AssignedId)*@
                                    </td>
                                    <td>
                                        <input type="checkbox"
                                               name="Details[@detail.IndexId].Complete"
                                               value="true"
                                               checked="@detail.Complete"
                                               disabled="@detail.EditAccess" />
                                    </td>
                                    <td>
                                        <input type="hidden"
                                               name="Details[@detail.IndexId].Name"
                                               value="@detail.Name"
                                               readonly />
                                        @Html.DisplayFor(r => detail.Name)
                                    </td>
                                    <td>
                                        <input type="hidden"
                                               name="Details[@detail.IndexId].StartDate"
                                               value="@detail.StartDate"
                                               readonly />
                                        @Html.DisplayFor(r => detail.StartDate)
                                    </td>
                                    <td>
                                        <input type="hidden"
                                               name="Details[@detail.IndexId].EndDate"
                                               value="@detail.EndDate"
                                               readonly />
                                        @Html.DisplayFor(r => detail.EndDate)
                                    </td>
                                    <td>
                                        <input type="hidden"
                                               name="Details[@detail.IndexId].LeadTech"
                                               value="@detail.LeadTech"
                                               readonly />
                                        @Html.DisplayFor(r => detail.LeadTech)
                                    </td>
                                    <td>
                                        <input type="hidden"
                                               name="Details[@detail.IndexId].Tech2"
                                               value="@detail.Tech2"
                                               readonly />
                                        @Html.DisplayFor(r => detail.Tech2)
                                    </td>
                                    <td>
                                        <input type="hidden"
                                               name="Details[@detail.IndexId].Tech3"
                                               value="@detail.Tech3"
                                               readonly />
                                        @Html.DisplayFor(r => detail.Tech3)
                                    </td>
                                </tr>
                            }
                        }
                    </tbody>
                </table>
            }
            <button>Update</button>
        </form>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM