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

时间:2015-04-21 07:01:25

标签: c# .net asp.net-mvc linq razor

我在尝试渲染部分视图时遇到错误:

  

类型' System.InvalidOperationException'的例外情况发生在   System.Web.Mvc.dll但未在用户代码中处理

     

附加信息:传递到字典中的模型项是   类型   ' System.Data.Entity.DynamicProxies.Post_206B6491B2DC6BC95A9910F33BF20B9F1973E064A753CBEDF9E6C72F08A98532&#39 ;,   但是这个字典需要一个类型的模型项   ' System.Collections.Generic.IEnumerable`1 [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);
    }

2 个答案:

答案 0 :(得分: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 :(得分:1)

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

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

  • 博客的模型名为(0)
  • 与该博客相关的类似博客(1)

<强>视图模型

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

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

BlogPostRelation(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)
}

您现在有一个模型(您可能想要添加条件,如果找不到),您可以在视图和局部视图中使用它,记住视图的规范是{ {1}}和Blog (0)。现在,视频模型中包含IEnumerable<Blog> (1)SingleBlogItem (0)

查看

SimilarBlogs (1)

因此,在主视图中,您可以像往常一样通过向模型添加@model PATH.TO.VIEWMODEL.BlogDetailViewModel @Html.DisplayFor(model => model.SingleBlogItem.Modified) 的前缀来分配模型(它是强类型的,因此会有intellesense)。然后是部分视图

调用partialview

SingleBlogItem (0)

在这里,您将视频模型中存在的类似帖子@Html.Partial("SimilarPosts",Model.SimilarBlogs) 传递给部分视图

<强> PartialView

Model.SimilarBlogs (1)

最后,您将Blog对象称为IEnumerable,对于该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> } 并且在通过该模型时从主视图中获取IEnumerable<Blog>进入部分视图

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

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