没有通过Html.BeginForm()将数据从视图传递给Action
本文关键字:视图 数据 Action Html BeginForm | 更新日期: 2023-09-27 18:04:13
我是asp.net mvc的新手,所以我失败的原因可能是一些基本的东西,但是经过近一天的工作,我现在似乎找不到它。
我要做的是从索引视图中获取编辑过的模型,并将其传递给第二个没有视图的动作,并在相关控制器中返回返回RedirectToAction("Index")
。在OrdersItemsController
中,我的动作如下:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult MarkedShipped(IEnumerable<orders_items> orderItems)
{
if (ModelState.IsValid)
{
foreach (var item in orderItems)
{
unitOfWork.GenericRepository<orders_items>().Update(item);
}
}
return RedirectToAction("Index");
}
在索引中。在视图的OrdersItems文件夹中的cshtml,我所做的是:
@model IEnumerable<Project.DataAccess.orders_items>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@using (Html.BeginForm("MarkedShipped", "OrdersItems", new { orderItems = Model }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.quantity)
</th>
<th>
@Html.DisplayNameFor(model => model.itemprice)
</th>
<th>
@Html.DisplayNameFor(model => model.trackingnumber)
</th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.quantity)
</td>
<td>
@Html.DisplayFor(modelItem => item.itemprice)
</td>
<td>
@Html.EditorFor(modelItem => item.trackingnumber)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.itemid })
</td>
</tr>
}
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="MarkShipped" class="btn btn-default" />
</div>
</div>
}
我的问题是,我无法从orderItems参数视图中获得模型,我不确定这是否是我想要完成的正确"语法";但是当动作被调用时,我得到的orderItems
是Count = 0
不是空值的orders_items
列表。
我也检查了是否有应用程序级异常,但Global.asax
中的Application_Error
没有异常
我现在卡住了一天,所以如果有人能告诉我如何将模型(或"编辑的数据")传递给我更新数据库的操作方向,我会非常感激。谢谢。
首先,你不能将一个集合模型(或者一个包含复杂对象或集合属性的模型)添加到表单路由参数中。内部助手调用.ToString()
方法如果你检查为表单标签生成的html你会看到类似
<form action=OrdersItems/MarkedShipped?orderItems=System.Collection.Generic.......
和绑定将失败,因为集合不能绑定到字符串。即使它可以工作,它也没有意义,因为它只会发回模型的原始值。
接下来,您不能使用foreach
循环来生成表单控件。再次,如果您检查生成的html,您将看到EditorFor()
方法生成的输入具有重复的id
属性(无效的html)和重复的name
属性,这些属性在您发布时没有必要的索引器绑定到集合。您需要使用一个for
循环或一个自定义的EditorTemplate
,用于typeof orders_items
使用for
循环意味着你的模型必须实现IList<T>
并且视图需要
@model IList<Hochanda.CraftsHobbiesAndArts.DataAccess.orders_items>
@using (Html.BeginForm()) // only necessary to add the controller and action if they differ from the GET method
{
....
@for(int i = 0; i < Model.Count; i++)
{
@Html.DisplayFor(m => m[i].quantity)
....
@Html.EditorFor(m => m[i].trackingnumber)
}
....
}
使用EditorTemplate
,在/Views/Shared/EditorTemplates/orders_items.cshtml
中创建一个部分(注意文件名必须与类名匹配)
@model Hochanda.CraftsHobbiesAndArts.DataAccess.orders_items
<tr>
<td>@Html.DisplayFor(m => m.quantity)</td>
....
<td>@Html.EditorFor(m => m.trackingnumber)</td>
....
</tr>
,然后在主视图(你可以使用IEnumerable<T>
)
@model IEnumerable<Hochanda.CraftsHobbiesAndArts.DataAccess.orders_items>
@using (Html.BeginForm())
{
<table class="table">
<thead>
....
<thead>
<tbody>
@Html.EditorFor(m => m)
</tbody>
</table>
....
}
EditorFor()
方法接受IEnumerable<T>
,并将根据EditorTemplate
在这两种情况下,如果你检查html,你现在会看到正确的名称属性,当你发布
时,你需要绑定模型。<input type="text" name="[0].trackingnumber" ... />
<input type="text" name="[1].trackingnumber" ... />
<input type="text" name="[3].trackingnumber" ... />
此处用Try For代替foreach。
@for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.quantity)
</td>
<td>
@Html.DisplayFor(modelItem => item.itemprice)
</td>
<td>
@Html.EditorFor(modelItem => item.trackingnumber)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.itemid })
</td>
</tr>
}
检查这个:- http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/
您可以执行以下操作
for (int i = 0; i < @ViewBag.Persons; i++)
{
<li>
<table>
<tr>
<td>
@Html.LabelFor(m => m.Fullname,new { @id = "FullnameLabel" + @i })
</td>
<td>
@Html.TextBoxFor(m => m.Fullname, new { @id = "Fullname" + @i })
</td>
</tr>
通过这种方式,每个html元素都有自己唯一的id,并且可以从它们单独检索回信息。您可以使用for或Foreach。只要确保剃刀迭代器正常工作即可。您可以查看源代码中的元素id,看看它是否正常工作。