加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – Steve Sanderson的BeginCollectionItem帮助程序

发布时间:2020-12-16 07:16:25 所属栏目:asp.Net 来源:网络整理
导读:我正在使用Steve Sanderson的BeginCollectionItem助手并遇到了问题.我有一个表单,可以选择添加无限的奖励字段.我正在使用他的助手,因为它解决了这个问题,如何继续生成字段,而不必担心在提交表单时如何绑定它. 我在这个相同的形式有一些复选框,有一个未知的数
我正在使用Steve Sanderson的BeginCollectionItem助手并遇到了问题.我有一个表单,可以选择添加无限的奖励字段.我正在使用他的助手,因为它解决了这个问题,如何继续生成字段,而不必担心在提交表单时如何绑定它.

我在这个相同的形式有一些复选框,有一个未知的数量.这个与奖励的区别在于数据库调用后将知道未知数量,并且在代码到达视图时将会知道.

所以我的代码看起来像这样

public class FrmVm
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public bool Active { get; set; }

        public IList<WarrantyFeaturesVm> WarrantyFeaturesVm { get; set; } // this is the checkbox ones.
         public IList<RewardVms> RewardVms { get; set; } // this is the dyanmic one that I needed the helper for

        public CbCreditCardFrmVm()
        {
            Active = true;
            WarrantyFeaturesVm = new List<WarrantyFeaturesVm>();
             RewardVms = new List<RewardVms>();
        }
    }


    // view

    @foreach (var tier in Model.RewardVms)
    {
            @Html.Partial("GenerateReward",tier)   // in this partial view in the  BeginCollectionItem                 
     }



 @foreach (var warranties in Model.WarrantyFeaturesVm)
{
    using (Html.BeginCollectionItem("WarrantyFeaturesVm"))
    { 
      <span>@warranties.Name:</span>
      @Html.TextBoxFor(x => warranties.FeatureId)
      @Html.CheckBoxFor(x => warranties.HasFeature)
    }
}

我正在使用jquery使用serializeArray()提交数据.当它进入服务器时,它会正确绑定所有动态的,甚至将保修绑定到Collection(集合计数为1).但它永远不会绑定WarrantyFeaturesVm中的任何内容,一切都保留为默认值.

如果我删除使用(Html.BeginCollectionItem(“WarrantyFeaturesVm”)),它甚至不会绑定集合.

任何人都知道为什么它没有绑定集合中的任何东西?

编辑

// for loop (works)
<form method="post" id="" action="" class="ui-formwizard ui-helper-reset ui-widget ui-widget-content ui-corner-all" novalidate="novalidate">

<span id="" class="step ui-formwizard-content ui-helper-reset ui-corner-all" style="display: none;">

<input type="hidden" value="6aa20677-d367-4e2a-84f0-9fbe00deb191" name="WarrantyFeaturesVm[0].FeatureId" id="WarrantyFeaturesVm_0__FeatureId" data-val-required="The FeatureId field is required." data-val="true" class="ui-wizard-content ui-helper-reset ui-state-default">    <span>Purchase</span>
<input type="checkbox" value="true" name="WarrantyFeaturesVm[0].HasFeature" id="WarrantyFeaturesVm_0__HasFeature" data-val-required="The HasFeature field is required." data-val="true" class="ui-wizard-content ui-helper-reset ui-state-default"><input type="hidden" value="false" name="WarrantyFeaturesVm[0].HasFeature" class="ui-wizard-content ui-helper-reset ui-state-default">

</form>




//foreach loop beginItemCollection(does not work)


<form method="post" id="" action="" class="ui-formwizard ui-helper-reset ui-widget ui-widget-content ui-corner-all" novalidate="novalidate">

<span id="" class="step ui-formwizard-content ui-helper-reset ui-corner-all" style="display: inline;">

<input type="hidden" value="68ba9241-c409-4f4b-96da-cce13b127c1e" autocomplete="off" name="WarrantyFeaturesVm.index" class="ui-wizard-content ui-helper-reset ui-state-default">
<input type="hidden" value="6aa20677-d367-4e2a-84f0-9fbe00deb191" name="WarrantyFeaturesVm[68ba9241-c409-4f4b-96da-cce13b127c1e].war.FeatureId" id="WarrantyFeaturesVm_68ba9241-c409-4f4b-96da-cce13b127c1e__war_FeatureId" data-val-required="The FeatureId field is required." data-val="true" class="ui-wizard-content ui-helper-reset ui-state-default">            <span>Purchase</span>
<input type="checkbox" value="true" name="WarrantyFeaturesVm[68ba9241-c409-4f4b-96da-cce13b127c1e].war.HasFeature" id="WarrantyFeaturesVm_68ba9241-c409-4f4b-96da-cce13b127c1e__war_HasFeature" data-val-required="The HasFeature field is required." data-val="true" class="ui-wizard-content ui-helper-reset ui-state-default"><input type="hidden" value="false" name="WarrantyFeaturesVm[68ba9241-c409-4f4b-96da-cce13b127c1e].war.HasFeature" class="ui-wizard-content ui-helper-reset ui-state-default">

</span>

</form>





//for loop beginItemCollection (does not work)
<form method="post" id="" action="" class="ui-formwizard ui-helper-reset ui-widget ui-widget-content ui-corner-all" novalidate="novalidate">


<span id="" class="step ui-formwizard-content ui-helper-reset ui-corner-all" style="display: none;">

<input type="hidden" value="fe3fbc82-a2df-476d-a15a-dacd841df97e" autocomplete="off" name="WarrantyFeaturesVm.index" class="ui-wizard-content ui-helper-reset ui-state-default">
<input type="hidden" value="6aa20677-d367-4e2a-84f0-9fbe00deb191" name="WarrantyFeaturesVm[fe3fbc82-a2df-476d-a15a-dacd841df97e].WarrantyFeaturesVm[0].FeatureId" id="WarrantyFeaturesVm_fe3fbc82-a2df-476d-a15a-dacd841df97e__WarrantyFeaturesVm_0__FeatureId" data-val-required="The FeatureId field is required." data-val="true" class="ui-wizard-content ui-helper-reset ui-state-default">            <span>Purchase</span>
<input type="checkbox" value="true" name="WarrantyFeaturesVm[fe3fbc82-a2df-476d-a15a-dacd841df97e].WarrantyFeaturesVm[0].HasFeature" id="WarrantyFeaturesVm_fe3fbc82-a2df-476d-a15a-dacd841df97e__WarrantyFeaturesVm_0__HasFeature" data-val-required="The HasFeature field is required." data-val="true" class="ui-wizard-content ui-helper-reset ui-state-default"><input type="hidden" value="false" name="WarrantyFeaturesVm[fe3fbc82-a2df-476d-a15a-dacd841df97e].WarrantyFeaturesVm[0].HasFeature" class="ui-wizard-content ui-helper-reset ui-state-default">

</span>

<span id="adminSettings" class="step ui-formwizard-content ui-helper-reset ui-corner-all" style="display: inline;">

</form>

解决方法

好吧我想我知道这里发生了什么.

在第二个示例中,您执行了foreach,看起来您的cshtml就像这样(@符号可能不正确):

foreach (var war in Model.WarrantyFeaturesVm) {
    using (Html.BeginCollectionItem("WarrantyFeaturesVm")) {
        Html.HiddenFor(m => war.FeatureId)
        <span>@Html.DisplayFor(m => war.Name)</span>
        Html.HiddenFor(m => war.HasFeature)
    }
}

因为BeginCollectionItem使用其上下文来派生HTML名称和id,所以这就是你在id和名称中最终得到“war”的原因.模型绑定器正在查找它找到的名为“WarrantyFeaturesVm”的集合属性.然而,它正在WarrantyFeaturesVm视图模型中查找名为“war”的属性,它无法找到,因此不会绑定.

<input type="hidden" value="6aa20677-d367-4e2a-84f0-9fbe00deb191" 
    name="WarrantyFeaturesVm[68ba9241-c409-4f4b-96da-cce13b127c1e].war.FeatureId" 
    id="WarrantyFeaturesVm_68ba9241-c409-4f4b-96da-cce13b127c1e__war_FeatureId" .../>

在第三种情况下,它是类似的.它正在寻找它找到的WarranyFeaturesVm集合属性.然而,它寻找另一个收集项目.

<input type="hidden" value="6aa20677-d367-4e2a-84f0-9fbe00deb191" 
    name="WarrantyFeaturesVm[fe3fbc82-a2df-476d-a15a-dacd841df97e].WarrantyFeaturesVm[0].FeatureId" 
    id="WarrantyFeaturesVm_fe3fbc82-a2df-476d-a15a-dacd841df97e__WarrantyFeaturesVm_0__FeatureId" .../>

为了正确绑定,您的HTML必须与您的第一个HTML示例类似:

<input type="hidden" value="68ba9241-c409-4f4b-96da-cce13b127c1e" 
    name="WarrantyFeaturesVm.index" .../>
<input type="hidden" value="6aa20677-d367-4e2a-84f0-9fbe00deb191" 
    name="WarrantyFeaturesVm[68ba9241-c409-4f4b-96da-cce13b127c1e].FeatureId" 
    id="WarrantyFeaturesVm_68ba9241-c409-4f4b-96da-cce13b127c1e__FeatureId" .../>

就像我在评论中暗示的那样,您可以通过将BeginCollectionItem及其包装的所有内容放入局部视图中来实现此目的.部分视图将接收其自己的上下文,因为您的帮助程序将使用视图的@Model属性与强大类型的帮助程序,如:@ Html.WidgetFor(m => m.PropertyName).

另一方面,如果你真的需要在外部视图中呈现集合,我没有看到使用带有for循环和没有BeginCollectionItem的普通索引(基于整数)的任何问题.

更新

我挖了this old post from Phil Haack.摘录:

…by introducing an extra hidden input,you can allow for arbitrary
indices. In the example below,we provide a hidden input with the
.Index suffix for each item we need to bind to the list. The name of
each of these hidden inputs are the same,so as described earlier,
this will give the model binder a nice collection of indices to look
for when binding to the list.

<form method="post" action="/Home/Create">

    <input type="hidden" name="products.Index" value="cold" />
    <input type="text" name="products[cold].Name" value="Beer" />
    <input type="text" name="products[cold].Price" value="7.32" />

    <input type="hidden" name="products.Index" value="123" />
    <input type="text" name="products[123].Name" value="Chips" />
    <input type="text" name="products[123].Price" value="2.23" />

    <input type="hidden" name="products.Index" value="caliente" />
    <input type="text" name="products[caliente].Name" value="Salsa" />
    <input type="text" name="products[caliente].Price" value="1.23" />

    <input type="submit" />
</form>

BeginCollectionItem使用此索引方法来确保模型绑定发生.唯一的区别是它使用Guids而不是int作为索引器.但你可以手动设置任何索引器,如上面的Phil示例.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读