I have a list of Products. Each line has 'Delete' action. When I try to delete any row everything is true, but after second deleting ajax confirmation comes twice. Please help.
There are product list view.
@model IEnumerable<Domain.Entities.Product>
@{
ViewBag.Title = "Products";
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<h1>Products</h1>
<table class="Grid">
<tr>
<th>Name</th>
<th>Description</th>
<th>Price</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>@item.Name</td>
<td>@item.Description</td>
<td>@item.Price</td>
<td>
@using (Ajax.BeginForm("DeleteProduct", "Admin",
new AjaxOptions {
Confirm="Product was deleted!",
UpdateTargetId="DeleteProduct"
}))
{
@Html.Hidden("Id", item.Id)
<input type="image" src="../Images/Icons/DeleteIcon.jpg" />
}
</td>
</tr>
}
</table>
There are AdminController
[Authorize]
public class AdminController : Controller
{
private IProductRepository productRepository;
public AdminController(IProductRepository productRepository)
{
this.productRepository= productRepository;
}
public ViewResult Products()
{
return View(productRepository.Products);
}
[HttpPost]
public ActionResult DeleteProduct(int id)
{
Product prod = productRepository.Products.FirstOrDefault(p => p.Id == id);
if (prod != null)
{
productRepository.DeleteProduct(prod);
TempData["message"] = string.Format("{0} was deleted", prod.Name);
}
return RedirectToAction("Products");
}
}
And finally _AdminLayout.cshtml
<html>
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Admin.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
</head>
<body>
<div id="DeleteProduct">
@if (TempData["message"] != null) {
<div class="Message">@TempData["message"]</div>
}
@RenderBody()
</div>
</body>
</html>
You have everything funneled through a single AJAX operation, so the click of delete is finding two items to delete on the second click. The way to handle this is work some magic on resetting the bound items so either a) the deleted item is set up to show it is already deleted once confirmed or b) rebinding the entire set of items after a delete to get rid of the item that has been deleted.
As long as you continue to have an item that the client believes has not been deleted, you will continue to "delete both" each time you click.
The problem here is that you are calling the
DeleteProduct
action with AJAX and this action is performing a Redirect to the Products action. Except that the Products action is returning a full HTML instead of a partial. So you get thejquery.unobtrusive-ajax.js
injected twice into your DOM. So you get 2 confirmations on the second delete, 3 on the third and so on.So start by defining a partial containing the table records (
~/Views/Admin/_Products.cshtml
):and then modify your main view so that it uses this partial:
and finally modify your
DeleteProduct
controller action so that it no longer does any redirects but returns the partial instead after deleting the record: