ASP.NET MVC主页数据的母版页

4
我越用ASP.NET MVC,就越喜欢它。然而,在显示主页面上的模型数据方面,有几种方法。我不确定最佳解决方案是什么。
我的示例将是一个商务网站,在每个页面上输出产品类别列表,并显示访问者购物车的状态。
在asp.net web forms中,我通常会使用用户控件,每个控件都执行自己的数据绑定以检索所需数据。
在MVC中,所有数据都应通过控制器传递。
因此,关于类别,最简单的解决方案似乎是在控制器操作中通过视图数据传递它:
ViewData["Categories"] = _service.GetCategories();

然而,对于每个操作都这样做并不是很DRY,因此遵循本文,我创建了一个基础控制器,将所需数据添加到我的ViewData中:

    public class AppController : Controller
{
    IAppService _service;

    public AppController() { }
    public AppController(IAppService appService)
    {
        _service = appService;
        SetSiteData();
    }

    private void SetSiteData()
    {
        ViewData["Categories"] = _service.GetCategories();
    }
}

我随后为ViewMasterPage创建了一个扩展:
        public static void RenderCategoryList(this ViewMasterPage pg) {
        pg.Html.RenderPartial("CategoryList", pg.ViewData["Categories"]);
    }

而在我的MasterPage中:

        <div>
        <%this.RenderCategoryList(); %>
    </div>

这种方法看起来很简洁。然而,我也看到有人建议为您的MasterPage创建一个ViewModel。也许随着ViewModel数据的增长,这可能是更好的解决方案。
关于购物车状态,我想我会做类似的事情,但不确定RenderAction是否更合适(在ASP.NET MVC中何时使用RenderAction vs RenderPartial)。
谢谢, Ben
2个回答

7

虽然这样做可以实现,但我不会这么做有两个原因:

  1. 我不喜欢把数据存储在ViewState中,因为你实际上是将其强制转换为对象
  2. 通过要求一个基本控制器,您将功能限制在继承自此基本控制器的控制器上(尽管这可能不是问题)

我认为这将是使用RenderAction(MvcFutures项目的一部分)的完美用途。该助手可用于呈现另一个控制器上的操作。因此,您可能具有具有ListCategories操作的ProductController,您只需执行以下操作:

<% Html.RenderAction<ProductController>(x => x.ListCategories()); %>

ListCategories会调用:
_service.GetCategories();

它可能会将信息粘贴到自己的模型中。然后,它会将该模型传递给视图,该视图将是一个部分页面。


1
+1 for RenderAction,这几乎是一个完美的解决方案,在MVC2发布后,您可以缓存RenderAction的结果,它将变得更加完美。 - mxmissile
我需要做些什么来使用你上面使用的强类型 RenderAction 调用吗?我正在使用 mvc 2.0 预览版,似乎不能以这种方式构造 RenderAction 方法。 - Ben Foster

2

谢谢 - RenderAction非常适合这项任务。

我从这里得到了更多信息。

因此,为了让其他人受益,这是一个我输出购物车状态的示例:

Action:

    [ChildActionOnly]
    public ActionResult CartStatus()
    {
        return PartialView(_service.GetCartSummary());
    }

部分视图(绑定到 Models.Cart)

<div class="cartSummary">
<%if (Model.HasItems) { %>
    Cart Items: <%=Model.Items.Count() %> | Total: <%=Model.TotalItems %>
<%} else {%>
    Your cart is empty. Please buy stuff!
<%} %>

Master Page 的辅助方法:

    public static void RenderCartStatus(this ViewMasterPage pg) {
        pg.Html.RenderAction("CartStatus", "Catalog", null);
    }

最后,母版页:
<%this.RenderCartStatus(); %>

感谢您的建议。

我正在尝试实现这个解决方案,但我无法弄清楚在哪里创建主页面的帮助程序方法?我需要在其他地方创建另一个C#类文件吗? - JBeckton
@JBeckon - 是的,你可以创建一个静态类来包含这些扩展。只需确保在视图或web.config中引用命名空间即可。 - Ben Foster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接