MVC3. Подтверждение Ajax приходит дважды - PullRequest
0 голосов
/ 20 марта 2012

У меня есть список продуктов.Каждая строка имеет действие «Удалить».Когда я пытаюсь удалить любую строку, все верно, но после второго удаления ajax-подтверждение приходит дважды.Пожалуйста, помогите.

Есть список продуктов просмотра.

@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>

Есть 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");
    }
}

И наконец _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>

Ответы [ 2 ]

3 голосов
/ 04 января 2013

Проблема в том, что вы вызываете действие DeleteProduct с AJAX, и это действие выполняет действие Перенаправления на продукты. За исключением того, что действие Products возвращает полный HTML вместо частичного. Таким образом, вы получаете jquery.unobtrusive-ajax.js, введенный дважды в вашу DOM. Таким образом, вы получите 2 подтверждения при втором удалении, 3 при третьем и т. Д.

Итак, начнем с определения части, содержащей записи таблицы (~/Views/Admin/_Products.cshtml):

@model IEnumerable<Domain.Entities.Product>

<div>@ViewData["message"]</div>

<table class="Grid">
    <thead>
        <tr>
            <th>Name</th>
            <th>Description</th>
            <th>Price</th>
        </tr>
    </thead>
    <tbody>
        @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 = "Are you sure you wanna delete this product?", 
                                UpdateTargetId = "products"
                            })
                    )
                    {
                        @Html.Hidden("Id", item.Id)
                        <input type="image" src="@Url.Content("~/Images/Icons/DeleteIcon.jpg")" alt="Delete" />
                    }
                </td>
            </tr>
        }
    </tbody>
</table>

, а затем измените ваш основной вид, чтобы он использовал этот частичный:

@model IEnumerable<Product>

@{
    ViewBag.Title = "Products";
    Layout = "~/Views/Shared/_AdminLayout.cshtml";
}

<h1>Products</h1>
<div id="products">
    @Html.Partial("_Products")
</div>

и, наконец, измените действие контроллера DeleteProduct так, чтобы оно больше не делало перенаправлений, а вместо этого возвращает частичное после удаления записи:

[HttpPost]
public ActionResult DeleteProduct(int id)
{
    Product prod = productRepository.Products.FirstOrDefault(p => p.Id == id);
    if (prod != null)
    {
        productRepository.DeleteProduct(prod);
        ViewData["message"] = string.Format("{0} was deleted", prod.Name);
    }

    return PartialView("_Products", productRepository.Products);
}
1 голос
/ 20 марта 2012

У вас есть все, что делается с помощью одной AJAX-операции, поэтому щелчок по удалению позволяет найти два элемента для удаления при втором щелчке.Способ справиться с этим - применить магию для сброса связанных элементов, поэтому либо a) удаленный элемент настроен так, чтобы показать, что он уже удален после подтверждения, либо b) повторное связывание всего набора элементов после удаления, чтобы избавиться от элемента.это было удалено.

Пока у вас есть элемент, который, по мнению клиента, не был удален, вы будете продолжать "удалять оба" каждый раз, когда нажимаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...