2

オブジェクト Cart にバインドされた部分ビューがあります。Cart には 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>

注意すべき点が 2 つあります。1 つ目は、項目を削除するために 1 行ごとにフォームを使用していることです。

2 つ目は、ユーザーが項目の数量を変更できるようにしてから、更新ボタンをクリックして、すべての変更をコントローラー アクションに渡すことを試みたことです。

        // 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 を呼び出す前に製品を再度取得する必要があるという事実はあまり好きではありませんが、ID の代わりに製品をモデルからアクションに渡す方法がわかりませんでした。

ただし、主な問題は、値をポストバックできるようにカート全体をフォームにラップしてから、IE で正しく動作しない理由を考えるのにかなりの時間を費やしたことです。ネストされたフォーム

だから私はこれを回避する方法にこだわっています。アイテムを個別に削除する機能が必要ですが、ユーザーがアイテムの数量を変更して、すべての変更を一度にコントローラーに渡すことができるようにします。投稿を強制するにはJavaScriptを使用する必要があり、JavaScriptを有効にしなくてもすべてが機能する必要があるため、削除アクションにリンクを使用できません。

[アップデート]

カスタム モデル バインダーの更新を許可することは、より良い解決策でしょうか? このようにして、ビュー内で変更を行い、カート オブジェクトをコントローラーに戻すことができました。ただし、これが子コレクション (Cart.CartItems) で可能かどうかはわかりません。Amazon などのサイトを調べたところ、カート全体がフォームにラップされ、JavaScript が無効になっていると、グローバル更新ボタンと個々のアイテム削除ボタンの両方が同じアクションにポストバックされているように見えます。どんな助けでも大歓迎です。

ありがとう、ベン

4

1 に答える 1

0

ここには 1 つの方法しかなく、それは醜い方法です。すべての周りに 1 つのフォームがあります。次に、アクションでどのボタンが押されたかを確認する必要があります(リクエストでボタンの名前を取得します)。

FirefoxとIEの違いにより、さらに醜くなります。ボタンを押した場合、ie または firefox (どちらか覚えていない) は、押されたボタンの名前だけでなく、ボタンが押された場所も送信します。

ソリューションが JS 対応のブラウザーに依存できる場合は、より多くのオプションがあります。しかし、それは別の話です。

于 2010-02-15T22:40:37.020 に答える