部分视图错误 MVC 需要 IEnumerable 类型的模型项



我在尝试渲染部分视图时不断收到错误:

类型为"System.InvalidOperationException"的异常发生在 System.Web.Mvc.dll但未在用户代码中处理

其他信息:传递到字典中的模型项是 类型 "System.Data.Entity.DynamicProxies.Post_206B6491B2DC6BC95A9910F33BF20B9F1973E064A753CBEDF9E6C72F08A98532", 但是此字典需要类型的模型项 'System.Collections.Generic.IEnumerable'1[MyBlogger.Post]'.

部分视图:

IEnumerable<MyBlogger.Post>

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

主详细信息视图:

@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

主要细节操作:

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

正如其他人所说,是你的模型结构导致了问题。您将单个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>
}

理想情况下,您需要创建一个视图模型来保存视图的所有数据。 视图模型是一个类,表示要在视图中显示的数据。如果您使用过 Sql Server,则可以将其视为 sql 视图,在上下文中,它将内容收集到一个组中,然后可以在页面上使用。

在您的情况下,您希望通过视图实现 2 个特定操作。

  • 博客的模型被调用(0)
  • 与该博客关联的类似博客(1)

视图模型

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

在该代码中,我们设置了视图模型来保存视图所需的内容。它是该视图的模型。现在它只是设置为Blog (0)IEnumerable<Blog> (1)对象的表示。类似的博客与单个博客项目有什么关系?这是由您决定的。为了这篇文章的目的,我将添加一个简单的解决方案。

博客帖子关系 ( POCO 类 )

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)。现在作为SingleBlogItem (0)SimilarBlogs (1)包含在视图模型中

视图

@model PATH.TO.VIEWMODEL.BlogDetailViewModel
@Html.DisplayFor(model => model.SingleBlogItem.Modified)

所以在主视图中,你可以像往常一样分配模型,只需向模型添加一个前缀SingleBlogItem (0)(它是强类型,所以会有智能感知)。然后对于部分视图

调用部分视图

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

在这里,您将Model.SimilarBlogs (1)部分视图传递存在于视图模型中的类似帖子

部分视图

@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,对于该分部视图的模型没有错误,因为此分部视图需要IEnumerable<Blog>,并且在将该模型传递到分部视图Model.SimilarBlogs (1)时从主视图中获取该对象

最好记住,当视图显示时,视图需要显示的所有内容都打包在模型中,这是应该在控制器中完成的工作。

我知道我已将其创建为博客,而不是基于您问题中的实际模型。我只是不想在您创建的内容和对解决方案的简单描述之间混淆。我认为相对于类似的博客来说,描述为简单的博客文章会更容易,这似乎与提出的问题密切相关

最新更新