.net – ASP.NET MVC View throwing CS1061 error related to type of model object passed as ViewDdata to a view

asp.netasp.net-mvcnet

I'm working through the ASP.NET MVC article at http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx. (Note: Some of the constructs in this post were deprecated in MVC 1 RTM, so I've changed the code accordingly. Perhaps that's my problem.)

In my LINQ to SQL .dbml (in MyDB.designer.cs) the Category class (compiler generated) is defined as follows:

namespace MVC_Basics_1.Models
{
    ...
    [Table(Name="dbo.Categories")]
    public partial class Category : INotifyPropertyChanging, INotifyPropertyChanged
    {
        ...
    }

In my controller class I define a Categories action method as follows:

public ActionResult Categories()  // /Products/Categories/ maps here
{
    List<Category> categories = northwind.GetCategories();
    return View("Categories", categories);
}

I then create a Categories.aspx which is strongly typed as "MVC_Basics_1.Models.Category" which places the

<%@ ... Inherits="System.Web.Mvc.ViewPage<MVC_Basics_1.Models.Category>" %>

line at the top of the file.

Finally, in the .aspx I have:

<% foreach (var category in ViewData) { %>
    <li>
        <%= Html.ActionLink(category.CategoryName, new { action="List", category=category.CategoryName }) %>
    </li>
<% } %>

Two questions:

First, when I browse to /Products/Categories/ I get the error:

Compiler Error Message: CS1061: 'System.Collections.Generic.KeyValuePair' does not contain a definition for 'CategoryName' and no extension method 'CategoryName' accepting a first argument of type 'System.Collections.Generic.KeyValuePair' could be found (are you missing a using directive or an assembly reference?)

and the category view data object isn't recognizing any of the properties of the Category class.

What am I missing?

Second, the controller's Category() action method is returning a list of categories (typed as "List categories") as the viewdata for the view, but the view's ActionLink helper method references a "category.CategoryName". This doesn't make sense to me since I'm passing in an instance of categories (not Category) as the type. Since the controller's action method is returning a List doesn't this suggest the view needs to be typed as Categories?

UPDATE:

I realized a flaw in my question and in my approach to this. I was more focused on the error and comparing my results to the article I read than on my actual goal – kind of like not seeing the forest through the trees. When I thought about what I was actually trying to accomplish – passing a model data to the view – I stopped thing about the syntax error and started thinking about (a) the particular object I wanted to create in the controller and (b) which piece(s) of that data I wanted to pass to the view. Once I saw the forest through the trees, the answer became obvious to me. @Ufuk and @ryk helped me realize this.

Best Answer

You should strongly type the View to the List, not the model only.

<%@ ... Inherits="System.Web.Mvc.ViewPage<IEnumerable<MVC_Basics_1.Models.Category>>" %>

This should solve both of your problems I guess. First you couldn't browse it with a foreach becase your model was not implementing IEnumerable. Second List<Category> instances are lists, you have to refer to a member if you want to use Category class' properties.

Update

There is a problem in your View too. You are sending the list in Model, not in ViewData.Change your View like this:

<% foreach (var category in Model) { %>
    <li>
        <%= Html.ActionLink(category.CategoryName, new { action="List", category=category.CategoryName }) %>
    </li>
<% } %>
Related Topic