【问题标题】:MVC5 Add Item to ListMVC5 将项目添加到列表
【发布时间】:2013-11-17 03:57:45
【问题描述】:

给定一个模型:

public class Receipt: BaseEntity
{
    [Required(AllowEmptyStrings = false,ErrorMessage = "Please Select A Store")]
    public Store  Store { get; set; }
    public List<Item> Items { get; set; }
    public Item NewItem { get; private set; }
    [Required(AllowEmptyStrings = false,ErrorMessage = "ReceiptModel.EntryDate is required")]
    public DateTime EntryDate { get; set; }
    public Guid EntryOwner { get; set; }
    public string Name { get; set; }

    public double ReceiptTotal()
    {
        return Items.Sum(item => item.ItemPrice);
    }
    public Receipt()
    {
        Items = new List<Item>();
        EntryOwner = Guid.Empty;
        EntryDate = DateTime.Now;
        Store = new Store();
        NewItem = new Item();
     }       
}

还有一个控制器:

public class ReceiptController : Controller
{
    //
    // GET: /Receipt/

    public ActionResult Index()
    {
        Receipt receipt = new Receipt();
        return View(receipt);
    }

    [HttpPost]
    public ActionResult AddItem(Receipt receipt)
    {
        receipt.Items.Add(receipt.NewItem);
        if (ModelState.IsValid)
        {
            return View("Index", receipt);
        }
        return View("Index", receipt);
    }

还有一个视图:更新的视图 - 删除了所有部分页面并合并为一个页面

<form class="form-horizontal" method="POST" action="@Url.Action("AddItem","Receipt")">
<div class="jumbotron">
    <div id="main" class="panel panel-primary">

        <div class="panel-heading"> <h1 class="panel-title">Receipt Builder</h1></div>
        <div class="panel-body">

            <fieldset>
                @Html.LabelFor(model => model.Name)
                @Html.EditorFor(model => model.Name)

                @Html.LabelFor(model => model.Store.Name)
                @Html.EditorFor(model => model.Store.Name)

                @Html.LabelFor(model => model.EntryDate)
                @Html.EditorFor(model => model.EntryDate)
            </fieldset>

        </div>


    </div>
</div>

<table class="table table-bordered table-condensed table-hover table-responsive table-striped">
    <thead>
        <tr>
            <td>
                <label class="control-label">#</label>
            </td>
            <td>
                <label class="control-label">Item</label>
            </td>
            <td>
                <label class="control-label">Unit</label>
            </td>
            <td>
                <label class="control-label">Quantity</label>
            </td>
            <td>
                <label class="control-label">UnitPrice</label>
            </td>
            <td>
                <label class="control-label">Category</label>
            </td>
            <td>
                <label class="control-label">Total</label>
            </td>
        </tr>
        <tr>

                <td>
                    <button class="btn-sm btn-danger" style="border-radius: 50%; background-color: red;" name="Submit" id="Submit" type="submit">+</button>
                </td>

                <td>
                    @Html.EditorFor(model => model.NewItem.Name)
                </td>

                <td>
                    @Html.EditorFor(model => model.NewItem.UnitType)
                </td>

                <td>
                    @Html.EditorFor(model => model.NewItem.Quantity)
                </td>

                <td>
                    @Html.EditorFor(model => model.NewItem.UnitPrice)
                </td>

                <td>
                    @Html.EditorFor(model => model.NewItem.Category.Name)<br/>
                    @Html.EditorFor(model => model.NewItem.Category.IsTaxable)
                </td>

                <td>
                    @Html.EditorFor(model => model.NewItem.ItemPrice)
                </td>


        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model.Items)
        {
            <tr>
                <td>
                    @Model.Items.ToList().IndexOf(item) + 1
                </td>
                <td>
                    @Html.LabelFor(titem => item.Name)
                </td>
                <td>
                    @Html.LabelFor(titem => item.UnitType)
                </td>
                <td>
                    @Html.LabelFor(titem => item.Quantity)
                </td>
                <td>
                    @Html.LabelFor(titem => item.UnitPrice)
                </td>
                <td>
                    @Html.LabelFor(titem => item.Category.Name)
                </td>
                <td>
                    @Html.LabelFor(titem => item.ItemPrice)
                </td>
            </tr>
        }
    </tbody>

    <tfoot></tfoot>
</table>

【问题讨论】:

  • 看到我的回答没有解决它:你能分享ItemList部分视图的代码吗?我注意到还有一些Ajax,你能分享相关代码吗?
  • @JeroenVannevel 在您的建议之后,我实际上删除了 Ajax 部分,所以现在页面上只有一个表单。我还添加了请求/适用的部分视图
  • 只是一个想法:尝试将您的newItem 一代也放在单独的局部视图中。就像现在一样,它可能无法将输入字段绑定到实际的 newItem 对象,因为这只是当前模型中的一个字段。您可以使用@Html.Partial("_addItem", new Item()) 调用它。您能否详细说明您确定故障所采取的具体步骤,这是否行不通?
  • 因此,当我提交 newItem 时,obj 已正确填充,因此我相信绑定没问题。但是 List 始终为空。我尝试过将事情转移到他们自己的部分观点。最初这是从单一视图开始的。我非常接近在会话状态内设置收据对象。我以前就是这样工作的,但它并没有很好地遵循 MVC 模式......
  • 在那种情况下,我没有进一步的想法。旁注:使用会话不会违反 MVC 模式。它会让你的应用程序有状态。

标签: asp.net-mvc razor asp.net-mvc-5


【解决方案1】:

感谢This Link,我终于能够解决这个问题

正如建议的那样,这确实是一个具有约束力的问题。似乎对于复杂的集合,例如 Lists,我们实际上不能像我希望的那样利用 IEnumerable 的好处。这是由于数据在名称不明确的帖子中实际传递的方式。这是工作的最终代码(只需要更新视图)

 @for (int i = 0; i < Model.Items.Count(); i++)
        {
            <tr>
                <td>
                @(i+1)
                </td>
                <td>
                    @Html.TextBoxFor(m => m.Items[i].Name)
                </td>
                <td>
                    @Html.TextBoxFor(m => m.Items[i].UnitType)
                </td>
                <td>
                    @Html.TextBoxFor(m => m.Items[i].Quantity)
                </td>
                <td>
                    @Html.TextBoxFor(m => m.Items[i].UnitPrice)
                </td>
                <td>
                    @Html.TextBoxFor(m => m.Items[i].Category.Name)
                </td>
                <td>
                    @Model.Items[i].ItemPrice
                </td>
            </tr>
        }

生成的 HTML 使用其索引命名每个元素,即 Item[N].Name 现在可以正确绑定post数据了。

【讨论】:

    【解决方案2】:

    收据中的项目仅以文本形式显示,没有控件。因此,当您将数据发布回服务器时,ASP.NET MVC 无法从请求正文中找到此信息,并将 Receipt.Items 集合留空。

    您可以在 Html.HiddenFor() 方法的帮助下将有关输入收据的信息添加为部分视图中的隐藏字段。或者只是将输入的项目保存在数据库或其他地方,然后在返回 AddItem 视图之前将它们读入 Receipt.Items 集合。

    【讨论】:

    • 我不确定你的意思。 NewItem 属性被传入所有正确的值,但属性 List 每次都被传入为空。
    • 是的,你是对的。 NewItem 属性值由您使用 Html.EditorFor 方法添加的编辑器组成。但是对于 Items 集合,您的表单中不存在任何数据,因此在将数据发送回服务器后,此集合为空。让我们做一个小样本。只需在 Html.LabelFor 字段中的 Receipt Builder 中替换 Html.EditorFor 调用,将一些默认数据添加到 Receipt in Index 操作中,然后在提交表单后查看结果。回发后,您的收据数据也将为空。
    • 您的回答最终使我走上了我需要走的路,谢谢。
    猜你喜欢
    • 2020-09-20
    • 1970-01-01
    • 2015-08-28
    • 1970-01-01
    • 2020-06-23
    • 2019-11-29
    • 2017-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多