【问题标题】:ASP.Net MVC Database-driven menu with caching带有缓存的 ASP.Net MVC 数据库驱动菜单
【发布时间】:2010-12-30 10:32:25
【问题描述】:

我正在尝试为我的网站创建一个菜单。需要满足以下要求

  • 它必须是数据库驱动的,从数据库中提取数据来构建菜单结构
  • 需要缓存从数据库中提取的数据 - 我不想为每个页面请求都访问数据库

目前,我正在运行一个简单的示例,但我不知道如何集成缓存。我想我可能不得不重新设计我这样做的整个方式。这里是:

我有一个 ProductMenuAttribute,它从 DB 中提取数据,并将其存储在 ViewData 中:

public class ProductMenuAttribute: FilterAttribute, IActionFilter
{
    #region IActionFilter Members

    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext != null)
        {
            var context = filterContext.Result as ViewResult;
            if (context != null)
            {
                ProductsRepository repository = new ProductsRepository(Properties.Settings.Default.SqlConnectionString);

                context.ViewData.Add("ProductsList", repository.GetAllProductRanges());
            }
        }
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {

    }

    #endregion
}

在我的 Site.master 中,我从 ViewData 中提取数据并使用它来呈现我的菜单。这是我的无序菜单列表中的一个小 sn-p,它使用 CSS 设置样式。代码如下:

            <li>
                <%= Html.ActionLink("Products", "Index", "Products")%>

                <%  IQueryable<ProductRange> productRanges = ViewData["ProductsList"] as IQueryable<ProductRange>; %>

                    <% if (productRanges != null)
                       { %>

                    <ul>
                        <% foreach (ProductRange range in productRanges) 
                           { %>   
                            <li><%= Html.ActionLink(range.Name, "RangeDetails", "Products", new { id = range.ID }, null)%></li>
                        <% } %>
                    </ul>

                    <% } %>
            </li>

然后我用 [ProductMenu] 属性装饰每个控制器,如下所示:

[ProductMenu]
public class HomeController : BaseController
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult About()
    {
        return View();
    }
}

现在,每当我的控制器上的任何操作被命中时,都会调用 ProductMenuAttribute 类中的 OnActionExecuted 方法,该方法将设置 ViewData,最终将在我的 Site.Master 上使用来从数据库构建我的菜单,这时候我会调用任何操作。

现在的问题是 - 我如何在这个场景中添加缓存?我不知道从哪里开始,并且感觉我的解决方案不可缓存。

【问题讨论】:

  • 对于所有与代码相关的目的,这个菜单都是静态的,对吧?为什么不创建一个知道 ProductMenu 类的局部视图?这不会消除您的缓存问题,但对于像我这样的旁观者来说会看起来更干净。如果我在哪里更改菜单,我知道我会花费数小时弄清楚产品如何进入视图数据。我可能看不到将 [ProductMenu] 应用于控制器类。
  • 我同意局部视图会更简洁,但我的示例旨在简化。

标签: asp.net-mvc caching menu database-driven


【解决方案1】:

我认为我真正想要的是使用 MVC Futures 项目中的 Html.RenderAction() 辅助扩展。

这个想法是使用上面的方法来调用控制器上的一个动作,这将通过从数据库中提取数据来生成 HTML 菜单结构。然后我还使用简单的输出缓存来缓存数据几分钟..

这是迄今为止我发现的实现我想要的最简单的方法。

编辑: Phil Haack 最近在博客上写了这篇文章 - Html.RenderAction and Html.Action。一篇很棒的博文,涵盖了我所有的确切需求,并解释了所有问题。

为了让缓存正常工作,我需要将我的 Html.RenderAction() 调用放在 ViewUserControl 中,并设置如下 OutputCaching 指令:

<@ OutputCache Duration="100" VaryByParam="None" %>

然后我用Html.RenderPartial() 调用上面的代码,瞧,一切正常!

【讨论】:

    【解决方案2】:

    您可以将存储库修改为可感知缓存:请参阅以下两个问题: cached repositoryhttp cache

    【讨论】:

      【解决方案3】:

      我已经通过使用 Enterprise Library Caching 块来做到这一点。您检查缓存数据,如果没有缓存数据,则从数据库中的数据创建 html 字符串并将其放入缓存中,以便稍后在搜索缓存数据时输出纯字符串:D

      只是提到这样做的代码是在静态类中。我将发布示例,但我正在从头开始在 MVC2 中重写该应用程序,因此我没有手动编写代码。

      【讨论】:

        猜你喜欢
        • 2011-01-22
        • 1970-01-01
        • 1970-01-01
        • 2016-04-29
        • 2010-10-17
        • 1970-01-01
        • 2013-06-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多