tags:

views:

48

answers:

3

Here is my class...any pointers?

public class Cart
{
    private List<CartLine> lines = new List<CartLine>();
    public IList<CartLine> Lines { get { return lines.AsReadOnly(); } }

    public void AddItem(Product product, int quantity)
    {
        var line = lines.FirstOrDefault(l => l.Product.ProductID == product.ProductID);

        if (line == null)
            lines.Add(new CartLine { Product = product, Quantity = quantity });
        else
            line.Quantity += quantity;

    }

    public decimal ComputeTotalValue() 
    {
        return lines.Sum(l => l.Product.Price * l.Quantity);
    }

    public void Clear() 
    {
        lines.Clear();
    }

    public void RemoveLine(Product product)
    {
        lines.RemoveAll(l => l.Product.ProductID == product.ProductID);
    }
}

public class CartLine
{
    public Product Product { get; set;}
    public int Quantity { get; set;}
}

Adding the Action method in the controller.

public RedirectToRouteResult AddToCart(Cart cart, int productID, string returnUrl)
        {
            Product product = productsRepository.Products.FirstOrDefault(p => p.ProductID == productID);
            cart.AddItem(product, 1);
            return RedirectToAction("Index", new { returnUrl });
        }

        public RedirectToRouteResult RemoveFromCart(Cart cart, int productID, string returnUrl)
        {
            Product product = productsRepository.Products.FirstOrDefault(p => p.ProductID == productID);
            cart.RemoveLine(product);
            return RedirectToAction("Index", new { returnUrl });
        }

        public ViewResult Index(Cart cart, string returnUrl)
        {
            ViewData["returnUrl"] = returnUrl;
            ViewData["CurrentCategory"] = "Cart";
            return View(cart);
        }

My custom model binder:

public class CartModelBinder : IModelBinder
    {
        private const string cartSessionKey = "_cart";

        #region IModelBinder Members

        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            if (bindingContext.Model != null)
                throw new InvalidOperationException("Cannot update instances");
            Cart cart = (Cart)controllerContext.HttpContext.Session[cartSessionKey];
            if (cart == null)
            {
                cart = new Cart();
                controllerContext.HttpContext.Session["cartSessionKey"] = cart;
            }
            return cart;
        }
        #endregion
    }
A: 

The first thing that I can see without seeing your controller action method is that you have no properties that you can write to, so the presumption is that this object is a read-only model. At minimum, we need to see the controller action method(s) that use(s) this object, and, if available, the view(s).

UPDATE:

As I understand it, the purpose of the ModelBinder is to take the data received from the HTML form, query string and/or session data and populate an instance of a .NET class, and, conversely, provide data from that same class instance for use in an HTML form. From what I'm looking at, your Cart class has behaviors and storage, but no transportable data in the form of read/write properties. MVC uses .NET reflection to find the read/write properties in the class. Since you have no read/write properties in your class, your model binding is failing, because your custom ModelBinder has nothing to transport.

You might want to look at these two articles for model binding assistance:

http://odetocode.com/Blogs/scott/archive/2009/04/27/6-tips-for-asp-net-mvc-model-binding.aspx

http://odetocode.com/Blogs/scott/archive/2009/05/05/iterating-on-an-asp-net-mvc-model-binder.aspx

Neil T.
Hey Neil, I added all the relevant information, action methods on the controller. I also pasted the custom model binder that I am using.
CodeToGlory
A: 

If you override the model binder, then you are responsible for populating the object from the form post. In the custom model binder you show, you don't actually set the properties of Cart. You need to set its properties.

Haacked
A: 

Thanks for all the replies, but I figured the problem. It is a very silly thing pointed out by [email protected] forums

The problem lies in the line controllerContext.HttpContext.Session["cartSessionKey"] = cart;

It should simply be controllerContext.HttpContext.Session[cartSessionKey] = cart;

I still cannot believe I did not catch this one before.

CodeToGlory