naz786
naz786

Reputation: 495

Virtual property is not being set to an instance for product being added to shopping cart

I have an interface that allows products to be added to the shopping cart. If a product not in the cart already, a new Cart object is created and added to the cart. This is the Cart class:

public class Cart 
{
    [Key]
    public int RecordId { get; set; }
    public string CartId { get; set; }
    public int ProductId { get; set; }
    public int Count { get; set; }
    public DateTime DateCreated { get; set; }
    public virtual Product Product { get; set; }
}

(Notice the virtual Product property.)

If a product being added to the Cart is already in the Cart, then only the Count is incremented for that Cart object:

    public void AddItemToCart(Product product)
    {
        var cartItem = db.Carts.SingleOrDefault(c => c.CartId == ShoppingCartId &&
                                                 c.ProductId == product.Id);

        if (cartItem == null)
        {
            cartItem = new Cart
            {
                ProductId = product.Id,
                CartId = ShoppingCartId,
                Count = 1,
                DateCreated = DateTime.Now

            };
            db.Carts.Add(cartItem);
        }
        else
        {
            cartItem.Count++;
        }
        db.SaveChanges();
    }

However, when viewing the shopping Cart Index, I am getting an error becuase the Product virtual property is not set to instance. The Shopping Cart Index is trying to access the Product.Name, Product.Price properties to display cart records:

    @model ValueVille.Models.ShoppingCartViewModel

<table class="panel panel-default table cart-table">
    <tr>
        <th>
            Product Name
        </th>
        <th>
            Price (each)
        </th>
        <th>
            Quantity
        </th>
        <th>
            @Html.ActionLink("Empty", "EmptyCart", "ShoppingCart", "", new { @class = "btn btn-info" })
        </th>
    </tr>
    @foreach (var item in Model.CartItems)
    {
        <tr id="[email protected]">
            <td>
                @item.Product.Name
            </td>
            <td>
                £@item.Product.Price
            </td>
            <td id="[email protected]">
                @item.Count
            </td>
            <td>
                <a href="#" class="RemoveLink" data-id="@item.RecordId">Remove</a>
            </td>
        </tr>
    }
    <tr>
        <td>
            Total
        </td>
        <td></td>
        <td></td>
        <td id="cart-total">
            £@Model.CartTotal
        </td>
    </tr>
</table>

This is the ViewModel being loaded on the ShoppingCart Index page:

public class ShoppingCartViewModel
{
    public List<Cart> CartItems { get; set; }
    public decimal CartTotal { get; set; }
    public int CartCount;
}

ShoppingCart Index page controller action:

 // GET: ShoppingCart
        public ActionResult Index()
        {
            var cart = ShoppingCart.GetShoppingCart(this.HttpContext);

            var Students = db.Carts.Include("Product"); //edit by OP

            var viewModel = new ShoppingCartViewModel
            {
                CartItems = cart.GetCartItems(),
                CartTotal = cart.GetTotal(),
                CartCount = cart.GetCount()
            };
            return View(viewModel);
        }

This is the cart.GetCartItems() method implementation:

public List<Cart> GetCartItems()
{
    return db.Carts.Where(c => c.CartId == ShoppingCartId).ToList();
}

Upvotes: 1

Views: 781

Answers (2)

levent
levent

Reputation: 3634

change

public List<Cart> GetCartItems()
{
    return db.Carts.Where(c => c.CartId == ShoppingCartId).ToList();
}

to

public List<Cart> GetCartItems()
{
    return db.Carts.Include("Product").Where(c => c.CartId == ShoppingCartId).ToList();
}

Upvotes: 2

Code Ranger
Code Ranger

Reputation: 401

You need to add a foreign key attribute to the navigation property like so: [ForeignKey("ProductId")]

Upvotes: 0

Related Questions