Asp.net mvc For循环中的MVC Ajax表单
我在For循环中使用Ajax.BeginForm,它允许我为For循环中的每个项目发布到控制器。最初,for循环在页面加载时正确呈现每个项目。 当控制器处理了从Ajax.beginnform正确填充的传入视图模型后,该方法将新生成的视图模型发送回视图,但是我的For循环中的每个项目现在都是重复的,并且所有文本框现在都具有提交的视图模型的值 非常困惑如何正确构造此代码,我需要提交基于ajax和部分视图的工作。我确实考虑过使用JQuery提交,但担心会丢失AntiForgeryToken,而且Ajax.BeginForm是一种更优雅的方法。非常感谢您的帮助。也很乐意提供更多信息 查看Asp.net mvc For循环中的MVC Ajax表单,asp.net-mvc,asp.net-ajax,ajax.beginform,Asp.net Mvc,Asp.net Ajax,Ajax.beginform,我在For循环中使用Ajax.BeginForm,它允许我为For循环中的每个项目发布到控制器。最初,for循环在页面加载时正确呈现每个项目。 当控制器处理了从Ajax.beginnform正确填充的传入视图模型后,该方法将新生成的视图模型发送回视图,但是我的For循环中的每个项目现在都是重复的,并且所有文本框现在都具有提交的视图模型的值 非常困惑如何正确构造此代码,我需要提交基于ajax和部分视图的工作。我确实考虑过使用JQuery提交,但担心会丢失AntiForgeryToken,而且Aja
@model Namespace.Models.MyParentViewModel
@for (int i = 0; i < Model.Items.Count; i++)
{
using (Ajax.BeginForm("SaveItem", "Controller", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "pensions" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary()
<div>
@Html.Hidden("ID", Model.Items[i].ID)
@Html.TextBox("TheName", Model.Items[i].TheName, new { @class = "form-control", @id = "item-" + i})
<input type="submit" value="Save" class="btn save" name="Command" />
</div>
}
}
@model Namespace.Models.MyParentViewModel
@对于(int i=0;i
控制器
[HttpPost]
[ValidateAntiForgeryToken]
[ActionName("SaveItem")]
public ActionResult SaveItem(MyItemViewModel mivm, string Command)
{
if (ModelState.IsValid)
{
#do some logic
}
// Return a newly populated MyViewModel with updated mivm.
var model = PopulateMyParentViewModel();
return PartialView("_MyPartialView", model);
}
private MyParentViewModel PopulateMyParentViewModel()
{
List<MyItemsViewModel> lstItems = new List<MyItemsViewModel>();
foreach (var item in enity.items.OrderBy(p => p.ID).ToList())
{
var ExistingItem = new MyItemViewModel
{
ID = item.ID,
TheName = item.TheName
};
lstItems.Add(MyItemViewModel);
}
MyParentViewModel.Items = lstItems;
return MyParentViewModel
}
[HttpPost]
[ValidateAntiForgeryToken]
[操作名称(“保存项”)]
公共操作结果保存项(MyItemViewModel MIM,字符串命令)
{
if(ModelState.IsValid)
{
#做些逻辑分析
}
//返回新填充的MyViewModel和更新的MIM。
var model=PopulateMyParentViewModel();
返回PartialView(“MyPartialView”,model);
}
私有MyParentViewModel PopulateMyParentViewModel()
{
列表项=新列表();
foreach(enity.items.OrderBy(p=>p.ID.ToList()中的var item)
{
var ExistingItem=新的MyItemViewModel
{
ID=item.ID,
TheName=item.TheName
};
添加(MyItemViewModel);
}
MyParentViewModel.Items=lstItems;
返回MyParentViewModel
}
我不确定代码中的“养老金”是什么,我猜它是一个围绕循环生成的每个表单的div?如果是这样,您的问题如下:
-
首先,如果没有一个项目是相互关联的(也就是说,触发一个项目上的某些更新也会导致另一个项目被更新),则不应该浪费资源来将整个列表发送回浏览器——只考虑发送受影响的“记录”的更新显示即可。然后用响应更新相应的项
- 导致项目重复的原因:AjaxOptions类有一个属性
,我记得,它的默认值是InsertionMode
,这会导致重复项出现。为什么?您向服务器发送一个Ajax请求,服务器发回一个由整个列表填充的HTML片段,而不是一个条目,然后浏览器将该片段附加到现有记录中InsertionMode=InsertionMode.InsertAfter
- 如果重新生成项目以仅发回一条记录而不是全部记录,则只需使用(…)块在
周围添加唯一标识(=具有唯一的
属性)id
元素,将
设置为InsertionMode
并将InsertionMode=InsertionMode.Replace
属性设置为该UpdateTargetId
的
,如下所示:id
<div id="record-@i"> @using (Ajax.BeginForm("SaveItem", "Controller", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "record-" + i.ToString(), InsertionMode = InsertionMode.Replace })) { // ... } </div>
假设Ajax请求所做的更改是,无论何时隐藏记录,都会返回一个表行,其中的一个按钮现在显示“show”而不是“hide”,并返回与触发请求的按钮所属的人员相关的相同数据。 然后,当您发出直接(=非ajax,当您直接导航到页面时)请求时,您可以执行以下操作:public ActionResult UpdateRecord(Int64 id) { var _record = Repository.Get(id); // logic to hide and update record return PartialView("TableRow_Partial",_record); }
为此,必须将@model PeopleCollection ... <table> <thead> <tr> <td>Name</td> <td>Age</td> <td>Salary</td> <td>Hide</td> </tr> </thead> <tbody> @foreach (Person record in Model) { @Html.Partial("TableRow_Partial",record) } </tbody>
设置为InsertionMode
。所有这一切都是因为,当您发送一个ajax请求以仅使用一条记录执行某项操作时,您只需刷新一项——触发ajax调用的一项,然后您只需返回新行(一行!),并将旧的一行替换为新的一行InsertionMode.ReplaceWith
如果您真的希望每次处理记录时都将整个项目集合发送回客户机,只需将整个呈现的表发送给客户机,并以类似的方式将旧表替换为新表。谢谢,但对返回模型有点混淆。如果我使用您的解决方案中的代码,我可以将单个模型传递给控制器并在数据库中更新该模型,但是当控制器返回项目列表时,该列表将替换记录中的单个行-@I将替换for循环迭代中使用的整个列表,并且仍然会导致重复。“pensions”实际上是包裹整个局部视图的div,因为循环在其中。@model Person @{ AjaxOptions opts = new AjaxOptions() { UpdateTargetId = "person-row-" + Model.Id.ToString(), InsertionMode = InsertionMode.ReplaceWith // etc }; } ... <tr id="person-row-@Model.Id"> <td>@Model.Name</td> <td>@Model.Age</td> <td>@Model.Salary</td> <td> <!-- configure the BeginForm(..) call with the action name and a routeValue anonymous object as "new { id = Model.Id}" --> @using (Ajax.BeginForm(...)) { <input type="submit" value="@(Model.IsHidden ? "Show" : "Hide")" /> } </td> </tr>
public ActionResult UpdateRecord(Int64 id) { var _record = Repository.Get(id); // logic to hide and update record return PartialView("TableRow_Partial",_record); }