1

I am having a lot of trouble trying to get my View in MVC to pass two primitive values retrieved from the user, and pass them back to a controller, while the model used by the view is a totally different nested model.

I tried passing also passing the whole Product or ProducWithAttributes but it always shows up as null in the AddToCart controller.

"Basic" Classes

namespace EcommerceWebsite_1.Models
{
    using System;
    using System.Collections.Generic;
    
    public partial class Prod_Attribute
    {
        public int product_id { get; set; }
        public string property_name { get; set; }
        public string property_value { get; set; }
    
        public virtual Product Product { get; set; }
    }
}
namespace EcommerceWebsite_1.Models
{
    using System;
    using System.Collections.Generic;
    
    public partial class Product
    {
        
        public int current_quantity { get; set; }
        public int product_id { get; set; }
        public string name { get; set; }
        public decimal price { get; set; }
        public string cat_name { get; set; }
        public byte[] image { get; set; }
        public Nullable<int> Merchandise_payment_order_id { get; set; }
        public bool out_of_stock { get; set; }
        public Nullable<int> max_amnt_per_order { get; set; }
    
        
    }
}


Classes(nested in Products Controller)

public class ProductWithAttributes
        {
            public Product Prod { get; set; }
            public List<Prod_Attribute> Prod_attributes { get; set; }
            public int selectedQuant { get; set; }


        }
       public class ProductWithQuant
        {
            public int prod_id { get; set; }
            public int selectedQuant { get; set; }



        }

"Calling" Controller

public ActionResult DetailsForUser(int id)
        {

            Product product = db.Products.Find(id);
           
            List<Prod_Attribute> attributes_vals = db.Prod_Attribute.Where(p => p.product_id == id).OrderBy(c => c.property_name).ToList();
            int quantity_selection;
            if (product.max_amnt_per_order!= null)
            {
                quantity_selection = (int)product.max_amnt_per_order;
               }
            else
            {
                quantity_selection = product.current_quantity;
            }

            int[] quantity_selection_list = new int[quantity_selection];

            for (int i=1; i<= quantity_selection; i++)
            {
                quantity_selection_list[i - 1] = i;
              
            }

            ViewBag.Quantities = quantity_selection_list;

            return View(new ProductWithAttributes
            {
                Prod = product,
                Prod_attributes = attributes_vals
            });
        }

View

@using EcommerceWebsite_1.Models
@model EcommerceWebsite_1.Controllers.ProductsController.ProductWithAttributes

@{
    ViewBag.Title = "Details";
}

<h2>Details</h2>

<div>
    <h4>Product</h4>
    <hr />
    
    <dl class="dl-horizontal">


        <dt>
            @Html.DisplayNameFor(model => model.Prod.name)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Prod.name)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Prod.price)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Prod.price)
        </dd>

        <dd>
            @Html.DisplayFor(model => model.Prod.image)
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Prod.max_amnt_per_order)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Prod.max_amnt_per_order)
        </dd>
        @foreach (Prod_Attribute attr in Model.Prod_attributes)
        {
            <dt>
                @Html.DisplayFor(model => attr.property_name)
            </dt>

            <dd>
                @Html.DisplayFor(model => attr.property_value)
            </dd>
        }
        <dd class="form-group">
            @Html.Label("Desired Quantity: ", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model => model.selectedQuant, new SelectList(ViewBag.Quantities), "Select Quantity...", htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessage("", new { @class = "text-danger" })
            </div>
        </dd>
    </dl>
</div>
<p>
    @Html.ActionLink("Add to Cart", "AddtoCart", new { product_id = Model.Prod.product_id, selectedQuant = Model.selectedQuant})
    @Html.ActionLink("Back to List", "IndexByCategory", new { cat_name = Model.Prod.cat_name })
</p>

Final Controller(...which only shows null arguments)

public ActionResult AddToCart([Bind(Include = "product_id, selectedQuan")] ProductWithQuant prod_added_To)
        {
            
            if ((System.Web.HttpContext.Current.User != null) && System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
            {


                Product product = db.Products.Find(prod_added_To.prod_id);

                Added_to newAddition = new Added_to
                {
                    product_id = prod_added_To.prod_id,
                    member_id = User.Identity.GetUserId(),
                    time_product_added = DateTime.Now,
                    quantity = prod_added_To.selectedQuant,
                    discounted_price = (decimal) CalcDiscountPrice(product)


                };

                
                db.Added_to.Add(newAddition);

                db.SaveChanges();
                return View(product);
            }
            else
            {
                string returnUrl = Request.Url.Host + "/Products/IndexForUser/" + prod_added_To.prod_id.ToString();
                return RedirectToAction("Login", "Account", returnUrl );
            }

The Model of the view is a object having another object Product and a list of Objects, Prod_attributes. I am trying to get the selected quantity value of the product that the user wants to purchase and then pass back to another controller just the product id and the selected quantity. Alternatively, I could pass the entire Product object and selected quantity. I have tried different combinations but nothing is working because I keep getting a null received by the final controller, Login. What am I doing wrong? Many thanks in advance. I need a solution as soon as possible.

Community
  • 1
  • 1
Craig
  • 11
  • 2
  • Have you tried using a ViewModel, so basically it will have properties from prod_Attribute and from product itself. Than you can pass it to the view via controller action and retreive it in the View – Umar Aftab Apr 15 '19 at 19:02
  • @UmarAftab I think all my controllers were auto-generated/scaffolded based on a model, after i added custom edits. Is that what you mean? I am "@using" that model at the top of my view. – Craig Apr 15 '19 at 19:05
  • @Craig No, View models are different entities from Auto generated templates. Please check about what is view models and implement the same. Hope you are little confused with what is model and view model and data passing. Please check what is the usage of models and view models so that you can manage it. All the best. – Samaritan_Learner Apr 22 '19 at 09:27
  • To be simple, You have nested model for your view and controller right you needs to break down to separate View Model class in such a way how you are expecting in View the same needs to be initialized inside the controller or needs to be passed to view and then the same needs to be binded with values in the view then needs to pass back to controller. This below link will solve your doubts - https://stackoverflow.com/questions/4878937/why-should-i-use-view-models – Samaritan_Learner Apr 22 '19 at 09:32

0 Answers0