0

I currently have a View which retrieves a list from a view model and displays a table for each item inside it. Now, what I want to do is the following: every time a user clicks to the button I've displayed, the application makes a POST request sending the specific item related and storing it, with its own quantity, to the current Session. To clarify, here is my code:

ProductLists.cshtml

   @model B2BCommerce.Models.ViewModels.OrderViewModel

    @Styles.Render("~/Content/bootstrap.css")

    @{
        short indexSelected = 0;
        short i = 0;
        ViewBag.Title = "Product List";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }  

    <style>
        .center-table {
            margin: 0 auto !important;
            float: none !important;
        }
    </style>

    <h2><center>Shop</center></h2>
    <hr/>

    <div class="container">

<table class="table table-hover center-table">

            @foreach (B2BCommerceThesis.Models.ViewModels.ShoppingItem item in Model.shoppingItems)
            {

                using (Html.BeginForm("AddToShoppingCart", "Order", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
                {

                    @Html.AntiForgeryToken();


                    <tr>
                        <td rowspan="3"> PhotoName </td>
                        <td colspan="3">  <center>@Html.LabelFor(m => m.shoppingItems[i].p.Name) </center> </td>
                        <td rowspan="3">Description</td>
                    </tr>

                    <tr>
                        <td colspan="3">@item.c.CompanyName</td>
                    </tr>

                    <tr>
                        <th>@(item.p.Price + " " + item.CurrencyName)</th>
                        <th>@item.CategoryName</th>
                        <th>
                            @if (item.p.Weight!= null)
                            {
                                if (item.p.Length!= null)
                                {
                                    @("Peso: " + item.p.Weight+ item.WeightName + "<br>Length: " + item.p.Length+ item.LengthName)
                                }
                                else
                                {
                                    @("Peso: " + item.p.Weight+ item.WeightName )
                                }
                            }
                        </th>
                    </tr>

                    <tr>
                        <th colspan="2"></th>
                        <th>
                            @Html.DropDownListFor(m => m.shoppingItems[i].SelectedQuantity, new SelectList(item.QuantitySelectedItem, "selectedQuantity"))
                        </th>
                        <th><button name="insertButton" class="btn btn-info">Add to cart </button></th>
                    </tr>
                    <tr>
                        <input type="hidden" value="@i" id="indexElement" name="indexElement"/>
                    </tr>
                    @{ i++; }

                      }
            }


            </table> 
    </div>

OrderViewModel.cs

using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace B2BCommerce.Models.ViewModels
{
    public class ShoppingItem
    {
        public Product p;
        public Customer c;



        public short SelectedQuantity { get; set; }
        public List<short> SelectedQuantities{ get; set; }
        public string WeigthName{ get; set; }
        public string LengthName { get; set; }
        public string CurrencyName { get; set; }
        public string CatwgoryName { get; set; }

        public ShoppingItem()
        {
            p = new Product();
            c = new Customer();
            QuantitaProdottiSelezionati = new List<short>();
        }
    }

    public class SessionShoppingCart
    {
        public List<ShoppingItem> ShoppingCartItems { get; set; }
        public List<short> Quantities { get; set; }

        public SessionShoppingCart()
        {
            ShoppingCartItems = new List<ShoppingItem>();
            Quantities = new List<short>(); 
        }
    }

}

OrderController.cs

 public ActionResult AddToShoppingCart(ShoppingItem item)
    {
        short indexItem = Convert.ToInt16(Request["indexElement"].ToString());
        Session["Products"] = item;
        Session["Quantities"] = item.SelectedQuantity;

        return RedirectToAction("ProductList");
    }

    public ActionResult ProductList()
    {
        OrderViewModel vm = new OrderViewModel();
        vm.Load();
        return View(vm);

    }

    public ActionResult ShoppingCartDetail()
    {
        SessionShoppingCart sc = new SessionShoppingCart();

        sc.ShoppingCartItems = (List<ShoppingItem>)Session["Products"];
        sc.Quantities = (List<short>)Session["Quantities"];

        return View(sc);
    }

So, my question is: is there anyway to send a single shoppingItem object, related to the button pressed, as a parameter since I've populated this table dynamically?

Gab
  • 87
  • 3
  • 7
  • You view makes no sense. You have multiple forms but can only submit one form at a time. Your generating `name` attributes that have no relationship to your model that you want to bind in the POST method. Why are you not generating one form and allowing the user to edit all items in the collection and then posting back the whole model? –  Oct 27 '16 at 08:14
  • @StephenMuecke Thank you. I would like to display the list of products to the user, with the possibility to add them to the shopping cart (Session) with a specific quantity. Displaying back the whole model is a waste of performance IMHO and I'm not sure if it could resolve the problem because the main problem is to retrieve the *specific* item. – Gab Oct 27 '16 at 08:21
  • Seriously - your current view is worse performance. And will no doubt ensure your users never again use your site after they start editing half a dozen quantities and click a button only to find that their edits have been lost. Not to mention that you need to keep posting and redirecting and regenerating the view every time. –  Oct 27 '16 at 08:24
  • @StephenMuecke I know the solution itself is not the best in terms of performance but its just an experiment. So, according to your comments, I should pass a *OrderViewModel* object to the controller, making a control on the selected quantity of the list items in order to find which elements were selected. Sounds it legit? – Gab Oct 27 '16 at 08:33
  • 1
    All you need in the view is a `for` loop of custom `EditorTemplate` to render the items ID and the quantity (refer [this answer](http://stackoverflow.com/questions/30094047/html-table-to-ado-net-datatable/30094943#30094943) for how to correctly generate the view) and your `OrderViewModel` will be populated with the collection so you know the ID and each quantity, so you can save everything in one action (`Session` would not even be required) –  Oct 27 '16 at 08:36
  • Thank you so much @StephenMuecke. – Gab Oct 27 '16 at 08:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/126807/discussion-between-gab-and-stephen-muecke). – Gab Oct 27 '16 at 09:36

0 Answers0