【发布时间】:2017-07-18 20:20:16
【问题描述】:
所以我编写了一些代码来允许在 ASP.NET MVC 中使用 AJAX 动态添加和删除集合中的元素。将新项目添加到集合中按预期工作,但删除不会。模型集合按预期更新(通过索引删除了相应的项),但呈现的 HTML 始终显示最后一项已被删除(而不是指定索引处的项)。
例如,假设我有以下物品:
- 富
- 酒吧
- 巴兹
当我单击名为“Foo”的项目旁边的“删除”时,我希望生成的渲染 HTML 如下所示:
- 酒吧
- 巴兹
当我通过控制器操作进行调试时,情况似乎如此,因为模型上的 Names 集合仅包含这些项目。但是,返回给我的 AJAX 处理程序的呈现 HTML 是:
- 富
- 酒吧
我认为问题可能与缓存有关,但我没有尝试过(OutputCache 指令、在 $.ajax 中设置 cache:false 等)。
代码如下:
DemoViewModel.cs
namespace MvcPlayground.Models
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public class DemoViewModel
{
public List<string> Names { get; set; }
public DemoViewModel()
{
Names = new List<string>();
}
}
}
DemoController.cs
这里明显的问题在于 RemoveName 方法。我可以验证 PartialViewResult 的 Model 属性反映了我期望的集合状态,但是一旦呈现给客户端,HTML 就不是我期望的那样。
namespace MvcPlayground.Controllers
{
using MvcPlayground.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
public class DemoController : Controller
{
// GET: Demo
public ActionResult Index()
{
var model = new DemoViewModel();
return View(model);
}
[HttpPost]
public ActionResult AddName(DemoViewModel model)
{
model.Names.Add(string.Empty);
ViewData.TemplateInfo.HtmlFieldPrefix = "Names";
return PartialView("EditorTemplates/Names", model.Names);
}
[HttpPost]
public ActionResult RemoveName(DemoViewModel model, int index)
{
model.Names.RemoveAt(index);
ViewData.TemplateInfo.HtmlFieldPrefix = "Names";
var result = PartialView("EditorTemplates/Names", model.Names);
return result;
}
}
}
Names.cshtml
这是我用来渲染名称列表的编辑器模板。向集合中添加新项目时按预期工作。
@model List<string>
@for (int i = 0; i < Model.Count; i++)
{
<p>
@Html.EditorFor(m => m[i]) @Html.ActionLink("remove", "RemoveName", null, new { data_target = "names", data_index = i, @class = "link link-item-remove" })
</p>
}
Index.cshtml
这是加载的初始页面,这里没什么复杂的。
@model MvcPlayground.Models.DemoViewModel
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Demo</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="container-collection" id="names">
@Html.EditorFor(m => m.Names, "Names")
</div>
@Html.ActionLink("Add New", "AddName", "Demo", null, new { data_target = "names", @class = "btn btn-addnew" })
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
Index.js
此脚本处理对 AddName 和 RemoveName 的调用。这里的一切都按我的预期工作。
$('form').on('click', '.btn-addnew', function (e) {
e.preventDefault();
var form = $(this).closest('form');
var targetId = $(this).data('target');
var target = form.find('#' + targetId);
var href = $(this).attr('href');
$.ajax({
url: href,
cache: false,
type: 'POST',
data: form.serialize()
}).done(function (html) {
target.html(html);
});
});
$('form').on('click', '.link-item-remove', function (e) {
e.preventDefault();
var form = $(this).closest('form');
var targetId = $(this).data('target');
var target = form.find('#' + targetId);
var href = $(this).attr('href');
var formData = form.serialize() + '&index=' + $(this).data('index');
$.ajax({
url: href,
cache: false,
type: 'POST',
data: formData
}).done(function (html) {
target.html(html);
});
});
【问题讨论】:
标签: c# asp.net-mvc asp.net-mvc-5