【问题标题】:partial view error mvc requires a model item of type IEnumerable部分视图错误 mvc 需要 IEnumerable 类型的模型项
【发布时间】:2015-04-21 07:01:24
【问题描述】:

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

“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

MainDetails 操作:

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

【问题讨论】:

  • 我的 IEnumerable 中的 Foreach 项目显示每个帖子的标题?
  • 您将单个Post 返回到视图,然后调用一个期望Post 集合的部分。 typeof Post 本身是否包含IEnumerable&lt;Post&gt; 的属性?
  • 您没有向您的部分发送任何数据。当您应该使用this one 时,您正在使用this 重载。您应该获取“类似帖子”的列表/可枚举并将其设置为部分的模型。例如,您可以在 MainDetails 操作中获取类似帖子的列表,将其保存在 ViewBag 中并将其传递给部分。
  • 我如何尝试 ViewBag.posts = db.Posts.ToList();和 @Html.Partial("SimilarPosts", ViewData.ToList()) 仍然无法将任何内容返回到部分。
  • 我不知道你如何定义你的“相似帖子”。假设您将渲染所有帖子(就像您在评论中写的那样)。在MainDetails 操作中写入:ViewBag.posts = db.Posts.ToList();。然后,在您的MainDetails.cshtml 中,将这一行@Html.Partial("SimilarPosts") // here 替换为这一行@Html.Partial("SimilarPosts", ViewBag.posts) // here。请注意,我将存储在ViewBag 中的帖子作为Partial 方法的模型传递。

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


【解决方案1】:

正如其他人所说,是您的模型结构导致了问题。您将单个 Post 对象发送到您的主视图,但您的子视图需要一个 IEnumerable&lt;Post&gt;。这里最好的解决方案是创建一个包含两者的视图模型:

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

【讨论】:

    【解决方案2】:

    理想情况下,您希望创建一个视图模型来保存视图的所有数据。 viewmodel 是一个类,表示您要在视图中显示的数据。如果您使用过 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&lt;Blog&gt; (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)
    }
    

    你现在有一个模型(如果没有找到,你可能想要添加条件),你可以在视图和局部视图中使用它,记住视图的规范是有一个 @ 987654327@ 和 IEnumerable&lt;Blog&gt; (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&lt;Blog&gt; 并且当它将该模型 Model.SimilarBlogs (1) 传递到局部视图时从主视图中获取它

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

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

    【讨论】:

      猜你喜欢
      • 2019-09-10
      • 1970-01-01
      • 2017-11-26
      • 1970-01-01
      • 2023-03-25
      • 2011-09-06
      • 2020-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多