【问题标题】:MVC 5 BeginCollectionItem Model Always NullMVC 5 BeginCollectionItem 模型始终为空
【发布时间】:2017-02-15 10:55:47
【问题描述】:

正在尝试使用 Html.BeginCollectionItem 在我的应用程序中工作,并且正在努力获取要发布的数据。我想将项目添加到列表中,然后发布整个列表。我正在使用 ajax 和 jquery 在我的列表中添加和删除项目,这似乎有效。但是当我发布在我的控制器中收到的模型时,即使当我查看提琴手时,表单数据也包含我的所有信息。

有没有人在我的代码中看到我做错了一些简单的事情?

主视图:

@model Test.Models.TestList

@using (Html.BeginForm())
{

<div class="form-group">
    <div class="row">
        <label for="AssemblyText" class="col-sm-1 col-sm-offset-1 control-label">Assembly:</label>
        <div class="col-sm-2">
           <input type="text" id="assembly" />
        </div>
        <label for="QuantityText" class="col-sm-1 control-label">Quantity:</label>
        <div class="col-sm-2">
            <input type="text" id="Qty" />
        </div>
        <button type="button" id="AddAssembly">Add Button</button>
    </div>
</div>

<table id="Assemblies" class="table table-striped">
<thead>
    <tr>
        <th>Assembly</th>
        <th>Quantity</th>
        <th>Action</th>
    </tr>
</thead>
<tbody class="text-left">
        @if (Model != null)
        {
            foreach (var assembly in Model.mylist)
            {
                @Html.Partial("AssemblyRow", assembly)
            }
        }
</tbody>   
</table>
<div class="form-group">
    <input type="submit" id="submitbtn" class="btn btn-success" value="Submit" />
</div>
}

局部视图(AssemblyRow)

@model Test.Models.Test

<tr class="editorRow">
@using (Html.BeginCollectionItem("Assembly"))
{
<td>
    @Html.HiddenFor(m => m.assembly)
    @Html.TextBoxFor(m => m.assembly)    
</td>
<td>
    @Html.HiddenFor(m => m.Qty)
    @Html.TextBoxFor(m => m.Qty)
</td>
<td>
    <span class="dltBtn">
        <a href="#" class="deleteRow">Delete</a>
    </span>
</td>
}

我的模型很简单,看起来像...

public class TestList
{
    public List<Test> mylist { get; set; }
}


public class Test
{
    public string assembly { get; set; }
    public string Qty { get; set; }

}

我的控制器

    [HttpPost]
    public ActionResult PostMain(TestList model)
    {


        return View();
    }

我可以提供你们认为有帮助的任何其他代码,但我尽量用我认为相关的部分来保持简单。

感谢您的帮助!

编辑:提琴手的图片

【问题讨论】:

    标签: c# asp.net-mvc


    【解决方案1】:

    我没有看到提交按钮,因此无法确定您要提交的内容,但请尝试将 ActionResult PostMain(TestList model) 更改为:

    ActionResult PostMain(List<Test> model)
    

    【讨论】:

    • 如果有帮助,我添加了提交按钮和表单。将其更改为 List 模型不起作用,它仍然为空。不过感谢您的想法!
    • 您可以尝试删除两个@Html.HiddenFor() 吗?为每个字段设置 HiddenFor()TextBoxFor() 会导致每个字段被发送两次。
    • 不,同样的事情。 :(
    • 你能贴一张 Fiddler 的表单数据截图吗?
    • 已添加!我在列表中添加了两个元素...程序集:12 个,数量为 1,然后是另外 122 个,数量为 1。
    【解决方案2】:

    您需要使用编辑器模板而不是部分视图。主控制器上下文在部分视图中不可用。 Stackoverflow 上有很多帖子讨论这个问题。其中之一是 ASP.NET MVC 3 - Partial vs Display Template vs Editor Template

    【讨论】:

    • 这是错误的。 OP 正在从集合中动态添加和删除项目,在这种情况下您不能使用 EditorTemplate
    【解决方案3】:

    您的集合属性名为 mylist,因此您必须将该名称传递给 BeginCollectionItem 方法

    @using (Html.BeginCollectionItem("mylist"))
    {
        ....
    

    这将生成需要正确绑定到模型的带有name=mylist[xxxx].assembly"(其中xxxxGuid)的元素。

    但是,您的代码还有其他问题。 DefaultModelBinder 绑定与模型属性匹配的第一个名称/值对,并忽略任何后续具有相同名称的名称/值对。因为您在文本框之前为每个属性都有一个隐藏的输入,所以只有您发送到视图的初始值会在您提交时被绑定,而不是编辑后的值。您需要删除部分是的两个隐藏输入s

    @model Test.Models.Test
    <tr class="editorRow">
        @using (Html.BeginCollectionItem("mylist"))
        {
            <td>@Html.TextBoxFor(m => m.assembly)</td>
            <td>@Html.TextBoxFor(m => m.Qty)</td>
            <td>
                <span class="dltBtn"><a href="#" class="deleteRow">Delete</a></span>
            </td>
        }
    </tr>
    

    旁注:还不清楚初始&lt;div class="form-group"&gt; 中的html 是做什么用的。您包括 2 个输入和一个按钮,但这不会绑定到您的模型并且不会正确地将项目添加到您的集合中(您的添加按钮需要使用 ajax 来调用返回另一个部分视图并将其附加到 DOM 的服务器方法)

    【讨论】:

    • 这个解释有帮助!谢谢!我能够让它工作。
    • 为了搜索者的利益,如果您使用的是嵌套 VM,您的字符串可能需要使用点语法例如向下钻取。 @using (Html.BeginCollectionItem("mySubClass.myList"))
    猜你喜欢
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多