1

I have the following View Data:

public class ShoppingCartViewData
{
    public IList<IShoppingCartItem> Cart
    {
        get;
        set;
    }
}

I populate the viewdata in my controller:

viewData.Cart = CurrentSession.CartItems;

return View(viewData);

And send the data to the view and display it using:

<% for (int i = 0; i < Model.Cart.Count; i++ ) { %>
 <%= Html.TextBoxFor(m => m.Cart[i].Quantity)%>
    <%= Html.HiddenFor(m => m.Cart[i].Id) %>
<% } %>

I want to be able to catch the viewdata on the post. When I try:

[HttpPost]
public ActionResult UpdateCart(ShoppingCartViewData viewData)
{
    ...
}

When I run this I get a: System.MissingMethodException: Cannot create an instance of an interface.

Can anyone shed some light on this. What would I have to do to get this to work?

Many Thanks

2
  • What is the reason you are using an interface for IShoppingCartItem rather than a concrete implementation? Commented Apr 28, 2010 at 10:20
  • Do you found the solution? Commented Jul 23, 2015 at 8:51

4 Answers 4

1

You could try adding the formcollection as a parameter. And shouldn't viewdata be the viewmodel you're using?

[HttpPost]
public ActionResult UpdateCart(ShoppingCartViewModel viewModel, FormCollection collection)
{
    ...
}

Not sure if this is the exact solution, i'm also busy learning MVC2.0 and .NET4 ;-)

Sign up to request clarification or add additional context in comments.

6 Comments

I don't think this will solve the problem. It's becuase the data binder is trying to instantiate ShoppingCartViewData which contains an inteface without a concrete implementation.
Is there a way around it? Do I have to inject the object into ShoppingCartViewData?
Why are you using an interface here anyway?
The whole domain model is based on Interfaces. The data coming from Linq2Sql is cast to an Interface as dictated by the domain model. The model is in its own Core project and everything references it.
We have a problem of terminology here. You might want to use the terms ViewData and View Model. In your case, you need a View Model classes. ViewData is just something ASP.NET MVC offers to you where you can save some marginal data that can't go anywhere else. But for your case you need strongly typed views with strongly typed controller actions. Then you should be fine.
|
0

I'd create a model binder for your ViewModel, and then you can instantiate a concrete type that implements the appropriate interface when it binds to the method parameters.

You can insert logic into your model binder to read the form fields as appropriate and then instantiate the right IList or IShoppingCartItem data, so no need to worry about being pinned to a single implementation of the interface either.

2 Comments

Any examples? I am looking for a way for the custom binder to pass a IList<ShoppingCartItem> instead of the IList<IShoppingCart> and populate the values for it. Can't find any examples of that anywhere.
This looks like a good resource: dotnet.dzone.com/news/custom-aspnet-mvc-model-binder - basically, you just register your interface type with a custom model binder, and when you are returning the object to use, just make sure it implements the right type to pass into your method.
0

Given my two comments this is how I would do it:

// you don't need this 
// viewData.Cart = CurrentSession.CartItems; 

// return View(viewData); 

// do it like this
return View(CurrentSession.CartItems);

Then have a strongly typed View either this:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Administration.Master" Inherits="System.Web.Mvc.ViewPage<ShoppingCartViewData>" %>

or this:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Administration.Master" Inherits="System.Web.Mvc.ViewPage<List<IShoppingCartItem>>" %>

Also this code won't work. This will generate you a bunch of textboxes with the same name and id. You need to generate textboxes with a count and for that you won't be able to use Html.TextBoxFor(). You will have to revert to Html.TextBox() or create a new extension TextBoxFor() method which would also accept a number (for you count).

<% for (int i = 0; i < Model.Cart.Count; i++ ) { %> 
 <%= Html.TextBoxFor(m => m.Cart[i].Quantity)%> // this won't work, if you want to post back all textboxes after they are edited
    <%= Html.HiddenFor(m => m.Cart[i].Id) %> 
<% } %> 

HTH

1 Comment

But really, please rename the class ShoppingCartViewData to ShoppingCartViewModel.
0

I got the same exception after adding an 'int' parameter to an action method.

I discovered by putting a break point in the controllers constructor that one of the other action methods (not the one specified in the forms post arguments) was being called instead.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.