我有一个View,它使用foreach循环显示带有删除选项的学生列表。但是Html.hidden没有按预期获得正确的student.ID。
这是我的学生班:
public class Student
{
public Guid ID { get; set; }
public string Name { get; set; }
}
我的控制器
public ActionResult Index()
{
var students = db.Students.OrderBy(s => s.ID).ToList();
return View(students);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult DeleteStudent(Guid Id)
{
if (Id != null)
{
Student student = db.Students.Single(s => s.ID == Id);
if (student == null)
{
return View("Error");
}
db.Students.Remove(student);
db.SaveChanges();
return RedirectToAction("Index");
}
return View("Error");
}
我的观点
@model IEnumerable<MyProject.Models.Student>
@{ ViewBag.Title = "Student List"; }
<h2>@ViewBag.Title</h2>
<ul>
@foreach (var student in Model)
{
<li>
@Html.displayFor(modelItem => student.Name)
@using (Html.BeginForm("DeleteStudent", "MyController", FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.Hidden("Id", student.ID)
<input type="submit" value="Delete" class="btnSubmit">
}
</li>
}
</ul>
假设有3名学生的ID分别为1,2和3。但是当我尝试删除学生3时,在控制器上,参数Guid Id
的值为1,因此ID = 1的学生将被删除。
事实上,无论我删除哪个学生,Id
总是取名单上第一个学生的价值。
我做错了什么,或者更好的方法是什么?
答案 0 :(得分:3)
再次了解您的要求,@Html
助手并没有给您带来任何好处。您的基本设置是生成大量表单,每个表单只是为了删除一个项目而设计的。最低要求是识别物品的某种方式。目前的问题是,@Html.Hidden
同时生成name="ID"
和id="ID"
,并且不允许重复的ID,无法正确处理。
我可以通过以下几种方法来解决这个问题:
e.g。
@using (Html.BeginForm("DeleteStudent", "MyController", FormMethod.Post, new {id=student.ID})){
控制器只接受id值作为参数。这意味着您不需要隐藏字段。
e.g。
<input name="ID" value="@student.ID" type="hidden"/>
控制器只接受id值作为参数。
@Html.HiddenFor
,但控制器操作采用通用FormCollection
参数,您可以拉出单独命名的元素(现在可能是最差的选项)。通常,尽可能尝试使用@Html.xxxFor
方法。然后,他们为回发正确命名项目。
作为第二条规则,您不能使用foreach
外观来呈现@Html.xxxFor
,因为这些方法实际上解释了表达式并查找索引值。 foreach
不提供索引值,因此您必须使用简单的for
循环,以便表达式看起来像Model[i].Property
。
e.g。
for (int i = 0; i < Model.length; i++)
{
@Html.EditorFor(x=>Model[i].Name)
}
表达式中存在的索引会在输入字段中生成name="Name[0]"
,name="Name[1]"
等。
回到手头的问题:对于每个表单,您需要一个隐藏字段,因此您应该使用for
循环和@Html.HiddenFor
,如下所示:
for (int i = 0; i < Model.length; i++)
{
@using (Html.BeginForm("DeleteStudent", "MyController", FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(x=>Model[i].ID)
<input type="submit" value="Delete" class="btnSubmit">
}
}
此外,正如评论中所述,您的观看次数model
似乎有误。通常,您会使用IEnumerable
或IList
之类的:
@model IEnumerable<MyProject.Models.Student>
答案 1 :(得分:0)
我怀疑你总是获得相同GUID的原因是因为所有隐藏的输入控件都具有相同的ID。
如果内存服务,当MVC尝试将参数映射到表单元素时,它将匹配与参数名称匹配的第一个字段,查询字符串变量等(不区分大小写)。
您的表单有多个隐藏的输入控件,全部名为“ID”。只有第一个将映射到您的DeleteStudent操作的ID参数。其余的可能会被忽略。