我在尝试渲染部分视图时不断收到错误:
类型为"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)
时从主视图中获取该对象
最好记住,当视图显示时,视图需要显示的所有内容都打包在模型中,这是应该在控制器中完成的工作。
我知道我已将其创建为博客,而不是基于您问题中的实际模型。我只是不想在您创建的内容和对解决方案的简单描述之间混淆。我认为相对于类似的博客来说,描述为简单的博客文章会更容易,这似乎与提出的问题密切相关