我有一个布局页面,其中有一个部分视图。分部视图需要循环遍历视图模型上的一个属性,以显示类别列表。当显示一个类别时,我需要显示该类别中的文档列表。/Home/Index
工作,但当我试图查看/Documents/Category/{id}
时,我得到一个错误:
附加信息:传入字典的模型项的类型是'System.Collections.Generic.List ' 1[ViewModels. list]。,但是这个字典需要一个'ViewModels.HomeViewModel'类型的模型项。
_Layout.cshtml
...
<body>
@Html.Partial("_CategoryViewModel")
<div class="content">
@RenderBody()
</div>
HomeViewModel.cs
public class HomeViewModel {
...
public ICollection<DocumentCategory> Categories { get; set; }
public ICollection<Documents> Documents { get; set; }
...
}
_CategoryViewModel。cshtml(这应该显示所有类别的列表)
@model ViewModels.HomeViewModel
...
@foreach (DocumentCategory item in Model.Categories)
{
<li>
<a href="@Url.Action("Category", "Documents", new { @id = @item.CategoryId })" title="View documents in the @item.Name category">
<span class="fa fa-files-o"></span> @item.Name
</a>
</li>
}
DocumentsController.cs
public ActionResult Category(int id)
{
var thisCategory = _ctx.Categories.Get(c => c.CategoryId == id).FirstOrDefault();
IEnumerable<DocumentViewModel> docs = null;
if(thisCategory == null)
{
TempData.Add("errorMessage", "Invalid category");
} else {
docs = thisCategory.Documents.ToList();
}
return View("Category", docs);
}
正在发生的事情是有意义的-布局页面上的PartialView
需要枚举在我使用的ViewModel
中不存在的集合。我不知道如何实现这一点-唯一的方法似乎是添加一个类别属性,每个ViewModel
在我的网站。
默认情况下,使用@Html.Partial()
将把当前模型传递给局部视图,并且因为您的Category.cshtml
视图使用@model List<DocumentViewModel>
,那么List<DocumentViewModel>
将传递给期望HomeViewModel
的局部。
如果您想在每个页面上呈现HomeViewModel
的部分视图,那么使用@Html.Action()
调用返回部分
ChildActionOnly
方法。[ChildActionOnly]
public ActionResult Categories
{
var model = new HomeViewModel()
{
.... // initialize properties
}
return PartialView("_CategoryViewModel", model)
}
和布局
@Html.Action("Categories", yourControllerName)
// or
@{ Html.RenderAction("Categories", yourControllerName); }
在我看来,你有几个不同的选择。
1。使用Html.Action
并创建一个返回视图的Action
。
@Html.Action("Index", "Category") // Or your controller name.
我相信这种方法有一些性能缺陷,因为为了呈现动作的结果,整个MVC生命周期将再次运行。但是,您可以在调用它的视图中没有正确的模型的情况下呈现操作的结果。
有人可能会认为这破坏了MVC模式,但这可能是值得的。
2。在您的_Layout.cshtml
中使用通用模型(或接口),并让您的视图模型继承该模型。
在你的_Layout.cshtml
:
@model IBaseViewModel
让你所有的视图模型实现这个接口。
public interface IBaseViewModel
{
ICollection<DocumentCategory> Categories { get; set; }
}
public interface IBaseViewModel<T> : IBaseViewModel
{
T ViewModel {get; set;}
}
由于您将@Html.Partial("_CategoryViewModel")
放置在_Layout.cshtml
中,我认为它应该在所有页面中可见,因此我认为使用_Layout.cshtml
的所有控制器确保它获得所需的信息是合乎逻辑的,因此将Categories
添加到模型中。
我一直使用这种方法来处理面包屑和菜单信息(在所有页面中使用的东西)。然后我有一个基本控制器,确保Categories
填充正确的信息。