MVC 5 ViewModel не работает, как в MVC 4

Я постараюсь сразу перейти к делу. Мне помогли создать ViewModel здесь, на StackOverflow. Он отлично работал в MVC 4, но теперь, когда я конвертирую приложение в MVC 5, он не работает. В коде ничего не изменилось. У меня есть _navigation.cshtml, который является частичным, который отображается в моем Layout.cshtml, и ошибка находится в циклах For в этом частичном. Этот же код отлично работает в MVC 4. Вот код:

Моя ошибка находится на частичной странице во время цикла for, и я получаю сообщение об ошибке Ingredient в строке:

@foreach (Ingredient ingredient in Model.Ingredients)

и там же на любом другом цикле for там же. Ошибка говорит:

Не удалось найти имя типа или пространства имен «Рецепт» (вам не хватает директивы использования или ссылки на сборку?)

Вот мой код:

Модели/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; }
        }
    }

Модели/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; }
        }
    }

Модели/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; }
        }
    }

Контроллеры/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 (звездочки указывают на ошибку рядом с Ingredient и Recipe в цикле For)

@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>

Опять ошибки гласят:

Не удалось найти имя типа или пространства имен «Ингредиент» (вам не хватает директивы использования или ссылки на сборку?)

Не удалось найти имя типа или пространства имен «Рецепт» (вам не хватает директивы использования или ссылки на сборку?)

Вот скриншот ошибки в Visual Studio Рядом с тем же кодом без ошибок:

введите здесь описание изображения


person Eric Bishard    schedule 11.02.2014    source источник
comment
Вы можете отредактировать свой код вместо того, чтобы удалить и повторно опубликовать вопрос.   -  person szpic    schedule 11.02.2014
comment
Я чувствовал, что комментарии к опечаткам сбивают с толку. Сейчас все убрано. Пост удалил, чтобы дубликатов не было. Но это неконструктивно на данный момент.   -  person Eric Bishard    schedule 11.02.2014
comment
Вы пытались добавить пространство имен модели представления?   -  person Thanigainathan    schedule 11.02.2014


Ответы (4)


Ваше представление не знает, откуда взялись Ingredient или Recipe, вам нужно добавить ссылку на пространство имен, в котором находятся эти типы, добавить @using XXX.Models вверху вашего представления.

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

Кстати, у вас, похоже, есть полусырая реализация модели представления. В вашем NavigationViewModel вы ссылаетесь на модели предметной области. Обычно рекомендуется, чтобы все, что выставлено через модель представления, на самом деле было самой моделью представления. Итак, в вашем случае я бы представил пару новых моделей представления для представления Ingredient/Recipe, т.е.

public class IngredientViewModel
{
    ...
}

public class RecipeViewModel
{
    ...
}

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

Они будут созданы под XXX.ViewModels, что означает, что ваше представление будет выглядеть так:

@using XXX.ViewModels
@model NavigationViewModel

...
person James    schedule 11.02.2014
comment
Он удалил ошибку в представлении кода и правильно раскрасил текст ингредиентов и рецептов, но я все равно получаю ошибку во время выполнения. - person Eric Bishard; 11.02.2014
comment
Является ли XXX.Models отдельным проектом библиотеки классов или он скомпилирован на веб-сайте? Попробуйте очистить/сборку. - person James; 11.02.2014
comment
XXX.Models — это папка с моими моделями. Все в одном проекте. - person Eric Bishard; 11.02.2014
comment
@EricB вы используете NavigationViewModel, из этой модели вы ссылаетесь на Ingredient/Recipe, которые исходят из XXX.Models. Вы должны создать IngredientViewModel/RecipeViewModel и ссылаться на них из NavigationViewModel. Если модели есть, то using - это все, что вам нужно. - person James; 11.02.2014
comment
Есть ли возможность обновить свой ответ примером? - person Eric Bishard; 11.02.2014
comment
Что-то не так с реализацией, которую ROwan дал мне здесь: stackoverflow.com /вопросы/20184423/ - person Eric Bishard; 11.02.2014
comment
Что насчет PartialControler (ActionResult) и того, что я помещаю в RecipeViewModel и IngredientViewModel, я просто поместил следующую строку в каждую: - person Eric Bishard; 11.02.2014
comment
public IEnumerable‹Ingredient› Ingredients { get; задавать; } - person Eric Bishard; 11.02.2014
comment
public IEnumerable‹Recipe› Recipes { get; задавать; } - person Eric Bishard; 11.02.2014
comment
Но какие изменения я могу внести в свой контроллер сейчас? - person Eric Bishard; 11.02.2014
comment
Я благодарю вас за помощь, но без дальнейших инструкций я не понимаю, и я просто беру удары в темноте. У Rowan было то, что я считал хорошим решением, и я подумал, что оно должно хорошо работать и в MVC 5. Что произошло между версиями, что это больше не допустимый способ делать что-то? - person Eric Bishard; 11.02.2014

В каталоге Views находится файл web.config. В нем перечислены пространства имен, которые должны быть доступны для представлений. Вы добавили пространство имен к представлениям web.config в своем проекте mvc4, которого сейчас нет в проекте mvc5?

Листинг в представлениях web.config является своего рода глобальным using оператором, который применяется ко всем представлениям.

person Anders Abel    schedule 11.02.2014
comment
Позвольте мне проверить, я думал, что сделал. - person Eric Bishard; 11.02.2014
comment
Я бы добавил XXX.Models или XXX.ViewModels.RecipeLineViewModel? Я добавил первый, и моя ошибка изменилась на The model item passed into the dictionary is of type (System.Collections.Generic.List)1[GransabanaUSA.Models.Recipe], but this dictionary requires a model item of type (GransabanaUSA.ViewModels.RecipeLineViewModel). - person Eric Bishard; 11.02.2014
comment
Посмотрите в свой проект mvc4 и попробуйте сделать то же самое. Это сообщение об ошибке выглядит так, как будто что-то еще не так. Вы передаете не ту модель с вашего контроллера? - person Anders Abel; 11.02.2014

Ваше представление не знает, откуда взялись Ingredient или Recipe, вам нужно добавить ссылку на пространство имен, в котором находятся эти типы, добавить @using XXX.Models в верхнюю часть вашего представления.

person Anzeem S N    schedule 31.10.2016

Если в вашем приложении MVC есть области, проверьте, совпадают ли пространство имен ViewModel и ссылка на модель в представлении Razor.

Если пространство имен модели представления содержит области, например. Areas.WebApp.Models , эта модель представления не будет скомпилирована в представлении, когда вы напишете @model WebApp.Models.

Оба должны совпадать. Поэтому либо удалите Areas из пространства имен ViewModel, либо добавьте такое же полное имя в View.

person Kurmi Naidu    schedule 06.03.2020