2015-04-21 4 views
2

я получаю сообщение об ошибке при попытке вынести частичный вид:частичный вид ошибки MVC требует модель элемента типа IEnumerable

Исключение типа «System.InvalidOperationException» произошло в System.Web.Mvc .dll, но не был обработан в пользовательском коде

Дополнительной информации: модель элемент передается в словарь типа «System.Data.Entity.DynamicProxies.Post_206B6491B2DC6BC95A9910F33BF20B9F1973E064A753CBEDF9E6C72F08A98532», но этот словарь требует модель элемента типа 'System.Collections.Generic.IEnumerable1 [MyBlogger.Post]'.

PartialView:

IEnumerable<MyBlogger.Post> 


@foreach (var item in Model) { 

    <p class="text-left">Similar Article: <a href="#">@Html.DisplayFor(modelItem => item.Title)</a></p> 

} 

MainDetails Вид:

@model MyBlogger.Post 

@{ 
    ViewBag.Title = "MainDetails"; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 

<h2>@Html.DisplayFor(model => model.Title)</h2> 

<header class="intro-header"> 
    <div class="container"> 
     <div class="row"> 
      <div> 
       <div class="post-heading"> 
        @*<a href="#">*@ 
         <img class="img-responsive" src="~/Content/img/post-bg.jpg" alt=""> 

         <h1>@Html.DisplayFor(model => model.ShortDescription)</h1> 
        <p class="text-left">Posted by <a href="#">@Html.DisplayFor(model => model.BlogUserEmail)</a> on @Html.DisplayFor(model => model.PostedOn)</p> 
        <p class="text-left">Category <a href="#">@Html.DisplayFor(model => model.Category.Name)</a></p> 

        @*</a>*@ 
       </div> 
      </div> 
     </div> 
    </div> 
</header> 

<fieldset> 
    <div class="display-field"> 
     @*@Html.DisplayFor(model => model.BlogUserEmail)*@ 
    </div> 

    <div class="display-field"> 
     @Html.Raw(HttpUtility.HtmlDecode(Model.Description)) 
    </div> 

    <div class="display-field"> 
     @Html.DisplayFor(model => model.Modified) 
    </div> 
</fieldset> 
@Html.Partial("SimilarPosts") // here 

MainDetails Действие:

public ActionResult MainDetails(string urlslug) 
    { 
     Post post = db.Posts.First(m => m.UrlSlug == urlslug); 
     if (post == null) 
     { 
      return HttpNotFound(); 
     } 
     return View(post); 
    } 
+0

Элемент Foreach в моем IEnumerable отображает заголовок каждого сообщения? –

+1

Ваше возвращение к представлению «Post», а затем вы вызываете партию, которая ожидает коллекцию «Почта».Имеет ли typeof 'Post' сам свойство, которое является' IEnumerable '? –

+1

Вы не отправляете никаких данных в свои части. Вы используете [this] (https://msdn.microsoft.com/en-us/library/ee402898 (v = vs.118) .aspx) перегрузку, когда вы должны использовать [этот] (https: // msdn.microsoft.com/en-us/library/ee402926(v=vs.118).aspx). Вы должны получить список/перечисляемый для «похожих сообщений» и установить его как модель для частичного. Например, вы можете получить список подобных сообщений в действии 'MainDetails', сохранить его в' ViewBag' и передать его частичному. –

ответ

1

Как говорили другие, это ваша модельная структура, которая вызывает у вас проблемы. Вы отправляете отдельного объекта Post на ваш основной вид, но ваш дочерний вид ожидает IEnumerable<Post>. Лучшее решение здесь, чтобы создать модель представления, которая охватывает как:

public class PostViewModel 
{ 
    public Post CurrentPost { get; set; } 
    public IEnumerable<MyBlogger.Post> Posts { get; set; } 
} 

Затем заполнить его чем-то вроде:

public ActionResult MainDetails(string urlslug) 
{ 
    Post post = db.Posts.First(m => m.UrlSlug == urlslug); 
    List<Post> posts = db.Posts.ToList(); 

    PostViewModel model = new PostViewModel 
    { 
     CurrentPost = post, 
     Posts = posts 
    }; 

    if (post == null) 
    { 
     return HttpNotFound(); 
    } 

    return View(model); 
} 

Тогда ваш главный вид будет:

@model PostViewModel 

<h2>@Html.DisplayFor(model => model.CurrentPost.Title)</h2> 

<header class="intro-header"> 
    <div class="container"> 
     <div class="row"> 
      <div> 
       <div class="post-heading"> 
        @*<a href="#">*@ 
         <img class="img-responsive" src="~/Content/img/post-bg.jpg" alt=""> 

         <h1>@Html.DisplayFor(model => model.CurrentPost.ShortDescription)</h1> 
        <p class="text-left">Posted by <a href="#">@Html.DisplayFor(model => model.CurrentPost.BlogUserEmail)</a> on @Html.DisplayFor(model => model.CurrentPost.PostedOn)</p> 
        <p class="text-left">Category <a href="#">@Html.DisplayFor(model => model.CurrentPost.Category.Name)</a></p> 

        @*</a>*@ 
       </div> 
      </div> 
     </div> 
    </div> 
</header> 

<fieldset> 
    <div class="display-field"> 
     @*@Html.DisplayFor(model => model.CurrentPost.BlogUserEmail)*@ 
    </div> 

    <div class="display-field"> 
     @Html.Raw(HttpUtility.HtmlDecode(Model.CurrentPost.Description)) 
    </div> 

    <div class="display-field"> 
     @Html.DisplayFor(model => model.CurrentPost.Modified) 
    </div> 
</fieldset> 
@Html.Partial("SimilarPosts", Model.Posts) 

Тогда ваши частичные будут такими же:

@model IEnumerable<MyBlogger.Post> 

@foreach (var item in Model) { 
    <p class="text-left">Similar Article: <a href="#">@Html.DisplayFor(modelItem => item.Title)</a></p> 
} 
1

В идеале вы хотели бы создать viewmodel для хранения всех данных для представления. Viewmodel - это класс, который представляет данные, которые вы хотите отобразить в представлении. Если вы работали с Sql Server, вы можете думать о нем как о представлении sql, что в контексте оно собирает вещи в группу, которая затем может быть использована на странице.

В вашем случае у вас есть 2 конкретных действия, которые вы хотите достичь с помощью своего вида.

  • модель блога называют (0)
  • Подобные блоги, связанные с этим блог (1)

ViewModel

public class BlogDetailsViewModel{ 
    public Blog SingleBlogItem { get; set; } // (0) 
    public IEnnumerable<Blog> SimilarBlogs { get; set; } // (1) 
} 

В том кода, мы установили viewmodel для хранения того, что нам нужно для v МЭН. Это модель для этой точки зрения.Сейчас он просто задан как представления для объектов Blog (0) и IEnumerable<Blog> (1). Как похожие блоги связаны с одним элементом блога, хотя? Это вам решать. Я просто добавлю простое решение для целей этой публикации.

BlogPostRelation (ПОКО класс)

public class BlogPostRelation{ 
     public int Id {get; set;} 
     public int BlogId {get; set;} 
     public int SimilarBlogId {get; set;} 
} 

Таким образом, в этом классе каждая строка в таблице будут соединены с помощью пункта блога и ассоциированного блога элемента, который подобен. Когда вы сохраняете элемент блога, в котором есть похожие блоги, вы также добавляете в эту таблицу основной BlogId (0) и SimilarBlogId (1). Поэтому, если вы сохраните 4 похожих блогов, в этой таблице будет 4 строки с сохраненными блогами BlogId.

Контроллер

public ActionResult BlogDetails(int blogId){ 

    // First find the blog you want. We assign it here instead of in the 
    // new BlogDetailViewModel so that we can use it as a condition on 
    // the similiar blogs 
    Blog blog = context.Blog.firstOrDefault(b => b.BlogId == blogId); 

    BlogDetailViewModel model = new BlogDetailViewModel{ 
      SingleBlogItem = blog, 
      SimilarBlogs = context.BlogPostRelation.Where(b => b.BlogId == blog.BlogId).ToList() 
    } 

    // Now pass this viewmodel to the main view 
    return View(model) 
} 

Теперь у вас есть модель (вы, вероятно, необходимо добавить условия, если не найден), которые можно использовать в представлении и частичный вид, помня о том, что спецификации для вид должен был иметь Blog (0) и IEnumerable<Blog> (1). Какие теперь содержатся в ViewModel, как SingleBlogItem (0) и SimilarBlogs (1)

Посмотреть

@model PATH.TO.VIEWMODEL.BlogDetailViewModel 

@Html.DisplayFor(model => model.SingleBlogItem.Modified) 

Так вот в главном окне можно назначить модель, как обычно, просто добавив префикс SingleBlogItem (0) к модели (он строго типизирован, так что будет intellesense). А потом для PartialView

Позвони PartialView

@Html.Partial("SimilarPosts",Model.SimilarBlogs) 

Здесь проходят подобные сообщения, которые живут в ViewModel, как Model.SimilarBlogs (1) к PartialView

PartialView

@model IEnumerable<Blog> 

@foreach (var item in Model) { 
    <p class="text-left">Similar Article: 
     <a href="#">@Html.DisplayFor(modelItem => item.Title)</a></p> 
} 

Наконец, вы вызываете объект Blog как IEnumerable, для модели этого PartialView без ошибок, потому что это PartialView хочет IEnumerable<Blog> и получает, что на главном экране, когда он проходит эту модель Model.SimilarBlogs (1) в PartialView

Это хорошо помнить, что, когда отображается вид все вещи, которые должно отображаться в представлении, упакованы в модель, что является работой, которая должна выполняться в контроллере.

Я знаю, что создал это как блог, а не на основе ваших реальных моделей в вашем вопросе. Я просто не хотел смешиваться между тем, что вы создали, и простым описанием решения. Я подумал, что было бы проще описать как простое сообщение в блоге относительно подобных блогов, которое, похоже, тесно связано с заданным вопросом.