Eric B Eric B - 1 month ago 11
C# Question

MVC 5 ViewModel not working as it was in MVC 4

I will try to get straight to the point. I had some help building a ViewModel here on StackOverflow. It worked fine in MVC 4 but now that I am converting the application to MVC 5 it is not working. Nothing has changed in way of the code. I have a _navigation.cshtml which is a partial that is rendered in my Layout.cshtml and the error is within the For Loops in that Partial. This same code is working fine in MVC 4. Here is the code:

My error is in the partial page during the for loop and I get the error on

Ingredient
in the line:

@foreach (Ingredient ingredient in Model.Ingredients)


also in the same place on any other for loop in the same place. The error says:


The type or namespace name 'Recipe' could not be found (are you
missing a using directive or an assembly reference?)


Here is my code:

Models/Ingredient.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace XXX.Models
{
public class Ingredient
{
public int IngredientID { get; set; }
public string IngredientNameEs { get; set; }
}
}


Models/Recipe.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace XXX.Models
{
public class Recipe
{
public int RecipeID { get; set; }
public string RecipeNameEs { get; set; }
}
}


Models/IdentityModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using System.Web;
using Microsoft.AspNet.Identity.EntityFramework;
using XXX.Models;

namespace XXX.Models
{
// You can add profile data for the user by adding more properties to your ApplicationUser class,
// http://go.microsoft.com/fwlink/?LinkID=317594 for more.
public class ApplicationUser : IdentityUser
{
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(): base("DefaultConnection")
{
}

public DbSet<Ingredient> Ingredients { get; set; }
public DbSet<Recipe> Recipes { get; set; }

}
}


ViewModels/NavigationViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using XXX.Models;

namespace XXX.ViewModels
{
public class NavigationViewModel
{
public IEnumerable<Ingredient> Ingredients { get; set; }
public IEnumerable<Recipe> Recipes { get; set; }
}
}


Controllers/PartialsController.cs

using XXX.Models;
using XXX.ViewModels;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace XXX.Controllers
{
public class PartialController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();

public ActionResult Navigation()
{
NavigationViewModel viewModel;

viewModel = new NavigationViewModel();
viewModel.Ingredients = db.Ingredients.Where(i => i.IsProduct != false).ToList();
viewModel.Recipes = db.Recipes.ToList();

return PartialView("_Navigation", viewModel);
}
}
}


Partials/_Navigation.cshtml (Asterisks indicate error near Ingredient and Recipe in For Loop)

@model XXX.ViewModels.NavigationViewModel
@using XXX.Models
//edited for brevity..
<li class="has-dropdown">@Html.ActionLink(XXX.Views.Shared.CultureSwap.Products, "Products", "Ingredient")
<ul class="dropdown">
@*//From NavigationViewModel print out each Product*@
@foreach (*Ingredient* ingredient in Model.Ingredients)
{
<li><a href="/Ingredient/Products/#@ingredient.IngredientNameEs">@ingredient.IngredientNameEs</a></li>
}
</ul>
</li>

<li class="divider"></li>
<li class="has-dropdown">@Html.ActionLink(XXX.Views.Shared.CultureSwap.Recipes, "List", "Recipe")
<ul class="dropdown">
@foreach (*Recipe* recipe in Model.Recipes)
{
<li><a href="/Recipe/List/#@recipe.RecipeNameEs">@recipe.RecipeNameEs</a></li>
}
</ul>
</li>


Again the errors read:


The type or namespace name 'Ingredient' could not be found (are you
missing a using directive or an assembly reference?)

The type or namespace name 'Recipe' could not be found (are you
missing a using directive or an assembly reference?)


Here is a screenshot of the error in Visual Studio Next to the same code with no errors:

enter image description here

Answer

Your view doesn't know where Ingredient or Recipe come from, you need to add a reference to the namespace which those types are under, add @using XXX.Models to the top of your view

@model XXX.ViewModels.NavigationViewModel
@using XXX.Models
...
@foreach (Ingredient ingredient in Model.Ingredients)
{
    ...
}

On a side-note you appear to have a half-baked view model implementation. In your NavigationViewModel you are referencing, which appear to be, domain models. It's generally recommended that anything exposed via a view model, is in actual fact, a view model itself. So in your case, I would introduce a couple of new view models to represent an Ingredient / Recipe i.e.

public class IngredientViewModel
{
    ...
}

public class RecipeViewModel
{
    ...
}

public class NavigationViewModel
{
    public IEnumerable<IngredientViewModel> Ingredients { get; set; }
    public IEnumerable<RecipeViewModel> Recipes { get; set; }
}

These would be be created under the XXX.ViewModels which would mean your view would look like

@using XXX.ViewModels
@model NavigationViewModel

...
Comments