Проблема с вложенной формой в модели коллекции ASP.NET - PullRequest
2 голосов
/ 16 февраля 2010

У меня есть частичное представление, которое привязано к объекту Корзина. Корзина имеет коллекцию CartLines. Мой взгляд ниже:

        <tbody>
        <% foreach (var line in Model.Lines) { %>
        <tr>
            <td align="center"><%=Html.CatalogImage(line.Product.DefaultImage, 80) %></td>
            <td align="left">
                <%=Html.ActionLink(line.Product.Name, "Product", "Catalog",  
                    new { productId = line.Product.Id }, new { title = "View " + line.Product.Name })%>
            </td>
            <td align="right"><%= line.Product.Price.ToString("c")%></td>
            <td align="center">
                <%=Html.Hidden("lines[" + i + "].key", line.Product.Id) %>
                <%=Html.TextBox("lines[" + i + "].value", line.Quantity, new { @class = "quantity" })%>
            </td>
            <td align="right"><%= (line.LineTotal).ToString("c")%></td>
            <td>
                <%using (Ajax.BeginForm("RemoveFromCart", "Cart", 
                      new {ProductId = line.Product.Id, returnUrl = ViewData["returnUrl"]}, 
                      new AjaxOptions { UpdateTargetId="cart", LoadingElementId="loading" }))
                  {%>                           
                        <input type="image" src="<%=AppHelper.ImageUrl("delete.gif")%>" value="Remove item"  />
                <%} %>
            </td>
        </tr>
        <% i++; } %>
    </tbody>

Следует отметить две вещи. Во-первых, я использую форму в строке для удаления элементов.

Во-вторых, я попытался разрешить пользователям изменять количество позиций, а затем нажать кнопку обновления, чтобы передать все изменения в действие контроллера:

        // POST: /Cart/Update
    [HttpPost]
    public ActionResult Update(Cart cart, IDictionary<int,int> lines, string returnUrl)
    {
        foreach (var line in lines) {
            Product p = _catalogService.GetProduct(line.Key);
            cart.UpdateItem(p, line.Value);
        }

        if (Request.IsAjaxRequest())
            return PartialView("Cart", cart);
        else
            return RedirectToAction("Index", new { returnUrl });
    }

Обратите внимание, что я использую словарь, так как меня интересует только продукт и количество. Мне не очень нравится тот факт, что мне нужно снова получить продукт перед вызовом cart.UpdateItem, но я не мог понять, как передать Продукт из модели в мои действия вместо идентификатора.

Основная проблема, однако, заключается в том, что я довольно глупо завернул всю корзину в форму, чтобы можно было отправить обратно значения, а затем провел целый час, размышляя, почему в IE все работает неправильно - doh! вложенные формы

Так что я застрял на том, как обойти это. Я хочу иметь возможность удалять элементы по отдельности, но разрешить пользователю изменять количество элементов, а затем сразу передавать все изменения контроллеру. Я не могу использовать ссылки для своего действия по удалению, так как мне нужно было бы использовать javascript для принудительной публикации, и все должно работать без включенного javascript.

[Update]

Было бы лучшим решением разрешить обновления моего пользовательского связывателя модели? Таким образом, я мог бы внести изменения в свое представление и отправить объект корзины обратно в контроллер - хотя я не уверен, возможно ли это с дочерними коллекциями (Cart.CartItems). Я просматривал такие сайты, как Amazon, и казалось, что они оборачивают всю корзину в форму, и как глобальные кнопки обновления, так и отдельные кнопки удаления элементов возвращаются к тому же действию, когда JavaScript отключен. Любая помощь будет оценена.

Спасибо, Бен

1 Ответ

0 голосов
/ 16 февраля 2010

Здесь есть только один путь, и это ужасный путь. Имейте 1 форму вокруг всего. Затем в действии вы должны проверить, какая кнопка была нажата (вы получите название кнопки в запросе).

Это становится еще страшнее с различиями в Firefox и т. Д. Если у вас нажата кнопка ie или firefox (не помню, какая именно) отправляет не только название нажатой кнопки, но и место, где была нажата кнопка.

У вас есть больше возможностей, если ваше решение может использовать браузеры с поддержкой JS. Но это другая история.

...