【问题标题】:PartialView with a ViewModel on _Layout.cshtml_Layout.cshtml 上带有 ViewModel 的 PartialView
【发布时间】:2016-08-10 08:08:19
【问题描述】:

我有一个包含局部视图的布局页面。局部视图需要遍历视图模型上的属性以显示类别列表。显示类别时,我需要显示该类别中的文档列表。 /Home/Index 有效,但是当我尝试查看 /Documents/Category/{id} 时,出现错误:

附加信息:传入字典的模型项的类型为“System.Collections.Generic.List`1[ViewModels.DocumentViewModel]”,但此字典需要“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>&nbsp;@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 中不存在的集合。我不知道如何实现这一点 - 唯一的方法似乎是将 Categories 属性添加到我网站中的每个 ViewModel

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-4 viewmodel asp.net-mvc-viewmodel


    【解决方案1】:

    默认情况下,使用@Html.Partial() 会将当前模型传递给局部视图,并且因为您的Category.cshtml 视图使用@model List&lt;DocumentViewModel&gt;,所以List&lt;DocumentViewModel&gt; 被传递给期望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); }
    

    【讨论】:

    • 这非常有效。这似乎比让所有东西都继承自基础 ViewModel 更“干净”。感谢您的帮助。
    【解决方案2】:

    在我看来,您有几个不同的选择。

    1. 使用Html.Action 并创建一个返回您的视图的Action

    @Html.Action("Index", "Category") // Or your controller name.
    

    相信这种方法存在一些性能缺陷,因为整个 MVC 生命周期将再次运行以呈现操作结果。但是,您可以在调用它的视图中没有正确模型的情况下渲染操作的结果。

    也有人会争辩说这是breaks the MVC pattern,但它可能是值得的。


    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 填充了正确的信息。

    【讨论】:

      猜你喜欢
      • 2012-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多