ASP MVC3 - BeginCollectionItem返回空值

时间:2013-04-09 18:10:44

标签: jquery asp.net-mvc-3 asp.net-mvc-2 icollection

我正在尝试将Steve Sanderson's blog post用于将集合项绑定到模型。但是,我看到一些奇怪的行为,我在帖子或其他讨论中找不到答案。

在我的模型BankListMaster中,我有一个单独模型ICollection的{​​{1}}个对象。 BankAgentIdBankListMaster在我们的SQL数据库中具有一对多关系。

我在BankListAgentId页面上遇到了这个问题。当页面加载时,我们当前与正在处理的Edit项关联的三个代理ID正确加载。但是,如果我点击“保存”,我会看到BankListMaster对象(ICollection)有三个项目,但每个相应的字段都包含bankListAgentId值。

如果我选择null,那么按照blog post上的说明,Ajax会调用部分视图,该视图会正确附加到表中。

现在,如果我点击“保存”,我会看到Add another对象计数增加了一个项目,计数为4.所有最初使用ICollection加载的项目都包含{ {1}}字段值,但新附加项的GETnull字段包含正确的信息(新项目的所有其他字段均为AgentId)。

对于ASP MVC来说还是比较新的,所以我不确定发生了什么或者看什么方向。

以下是主视图中的表单。我在使用和不使用StateCode项目的情况下尝试了此操作并获得了相同的结果。

null

这是局部视图。我再次尝试使用和不使用@Html.Hidden项并获得相同的结果。

@model Monet.Models.BankListMaster

@{
    ViewBag.Title = "Edit";
}
    <fieldset>
        <legend>Stat(s) Fixed</legend>
        <table id="fixedRows">
            <thead>
                <tr>
                    <th>State Code</th>
                    <th>Agent ID</th>
                    <th></th>
                    <th></th>
                </tr>
           </thead>
           <tbody>

                @for (int i = 0; i < Model.Fixed.Count; i++)
                {
                     using (Html.BeginCollectionItem("BankListAgentId"))
                    {                        
                             @Html.HiddenFor(m => Model.Fixed[i].BankID)
                             @Html.HiddenFor(m => Model.Fixed[i].TableId)
                             @Html.HiddenFor(m => Model.Fixed[i].FixedOrVariable)   
                            <tr>
                                <td>
                                    @Html.DropDownListFor(m => Model.Fixed[i].StateCode,
                                        (SelectList)ViewBag.StateCodeList, Model.Fixed[i].StateCode)
                                </td>
                                <td>
                                    @Html.TextBoxFor(m => Model.Fixed[i].AgentId)
                                    @Html.ValidationMessageFor(m => Model.Fixed[i].AgentId)
                                </td>
                                <td>
                                    <a href="javascript:void(0)" class="deleteRow">delete</a>
                                </td>
                                @*<td><a href="#" onclick="$('#item-@Model.AgentId').parent().remove();" style="float:right;">Delete</a></td>*@
                            </tr>  

                    }
                }

           </tbody>

        </table>
        <br />
        <a href="javascript:void(0)" class="addFixed">Add Another</a>
    </fieldset>

这是Ajax调用

@Html.Hidden

这是调用局部视图的控制器方法

@model Monet.Models.BankListAgentId

@{
    Layout = null;
}
@using (Html.BeginCollectionItem("BankListAgentId"))
{ 
    @Html.HiddenFor(model => model.TableId)        
    @Html.HiddenFor(model => model.BankID)
    @Html.HiddenFor(model => model.FixedOrVariable)

    <tr>
        <td>
            @Html.DropDownListFor(model => model.StateCode,
                (SelectList)ViewBag.StateCodeList, Model.StateCode)
        </td>
        <td>
            @Html.EditorFor(model => model.AgentId)
            @Html.ValidationMessageFor(model => model.AgentId)
        </td>
        <td>
            <a href="javascript:void(0)" class="deleteRow">delete</a>

        </td>
        @*<td><a href="#" onclick="$('#item-@Model.AgentId').parent().remove();" style="float:right;">Delete</a></td>*@
    </tr>
}

这是$(document).ready(function () { $(".addFixed").click(function () { $.ajax({ url: '@Url.Action("BlankFixedRow", "BankListMaster")', dataType: 'html', cache: false, success: function (html) { $("#fixedRows > tbody").append('<tr>' + html + '</tr>'); } }); }); }); 型号

    public ViewResult BlankFixedRow()
    {
        SelectList tmpList = new SelectList(new[] { "AL", "AK", "AS", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FM", "FL", "GA", "GU", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MH", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NA", "NM", "NY", "NC", "ND", "MP", "OH", "OK", "OR", "PW", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "US", "VT", "VI", "VA", "WA", "WV", "WI", "WY" });
        ViewBag.StateCodeList = tmpList;

        return View("FixedPartialView", new BankListAgentId());
    }

这是BankListMaster模型

public partial class BankListMaster
{
    public BankListMaster()
    {
        this.BankListAttachments = new HashSet<BankListAttachments>();
        this.BankListAgentId = new HashSet<BankListAgentId>();
    }

    public int ID { get; set; }
    public string BankName { get; set; }
    public string LastChangeOperator { get; set; }
    public Nullable<System.DateTime> LastChangeDate { get; set; }

    public virtual ICollection<BankListAttachments> BankListAttachments { get; set; }
    public virtual ICollection<BankListAgentId> BankListAgentId { get; set; }
}

这是从帖子上的表单通过fiddler发送回控制器的内容。索引为123的项目是最初从数据库中提取的项目。最后一项是通过jQuery / Ajax调用添加到局部视图的。

enter image description here

2 个答案:

答案 0 :(得分:1)

我的解决方案是:html.beginCollectionItem中使用的所有内容都必须在局部视图中。 所以你的解决方案可能是这样的:

主视图

 @model Monet.Models.BankListMaster

 @{
     ViewBag.Title = "Edit";
 }
     <fieldset>
         <legend>Stat(s) Fixed</legend>
         <table id="fixedRows">
         <thead>
              <tr>
                   <th>State Code</th>
                   <th>Agent ID</th>
                   <th></th>
                   <th></th>
             </tr>
        </thead>
        <tbody>

            @for (int i = 0; i < Model.Fixed.Count; i++)
            {
                 @Html.Partial("name", item)     
            }

       </tbody>

    </table>
    <br />
    <a href="javascript:void(0)" class="addFixed">Add Another</a>
</fieldset>

部分视图“名称”

 @model Monet.Models.BankListMaster

 using (Html.BeginCollectionItem("BankListAgentId"))
 {                        
      @Html.HiddenFor(m => Model.Fixed[i].BankID)
      @Html.HiddenFor(m => Model.Fixed[i].TableId)
      @Html.HiddenFor(m => Model.Fixed[i].FixedOrVariable)   
      <tr>
           <td>
                @Html.DropDownListFor(m => Model.Fixed[i].StateCode,
                  (SelectList)ViewBag.StateCodeList, Model.Fixed[i].StateCode)
           </td>
           <td>
                @Html.TextBoxFor(m => Model.Fixed[i].AgentId)
                @Html.ValidationMessageFor(m => Model.Fixed[i].AgentId)
           </td>
           <td>
                <a href="javascript:void(0)" class="deleteRow">delete</a>
           </td>
           @*<td><a href="#" onclick="$('#item-@Model.AgentId').parent().remove();" style="float:right;">Delete</a></td>*@
           </tr>  

 }

这不是完整的解决方案,但你必须这样做,它对我有用。 希望这会有所帮助!

答案 1 :(得分:0)

我在几个小时内遇到了类似的问题。当我的项目集合(Choices)包含多个项目时,它将返回null。但是,就像你一样,我的数据看起来很好:

{
    "QuestionTemplateId":"1",
    "Position":"0",
    "CardId":"1",
    "Label":"Question#1",
    "AdminComments":"",
    "Type":"ComboBox",
    "ModelType":"MyProject.Areas.DGM.Models.ViewModels.Controls.ComboBoxViewModel",
    "ComboQuestionId":"1",
    "Choices.Index": ["dc0e6eea-5a8e-4971-8f9f-4d6e1c290300","52f2b780-c21e-4633-b880-bdff5d815eaf"],
    "Choices[dc0e6eea-5a8e-4971-8f9f-4d6e1c290300].Label":"Choice #1",
    "Choices[dc0e6eea-5a8e-4971-8f9f-4d6e1c290300].Score":"4",
    "Choices[52f2b780-c21e-4633-b880-bdff5d815eaf].Label":"Choice #2",
    "Choices[52f2b780-c21e-4633-b880-bdff5d815eaf].Score":"7"
}

然后我意识到我的问题可能与数据POST有关。当用户提交表单时,我会进行以下AJAX调用:

$("#questionForm").on('submit', function () {
    if ($(this).valid()) {
        var data = $(this).serializeObject(); // from here: http://stackoverflow.com/a/1186309/2835243
        $.ajax({
            type: 'POST',
            url: this.action,
            contentType: 'application/json',
            data: JSON.stringify(data) // this is what generated the above JSON
        });
    }
}

似乎为我解决的问题是将数据作为x-www-form-urlencoded(jQuery的AJAX的默认contentType)而不是json发送。所以我改变了我的AJAX调用以下内容:

$.ajax({
    type: 'POST',
    url: this.action,
    data: $(this).serialize()
});