ASP.Net MVC Управляемое базой данных меню с кэшированием
Я пытаюсь создать меню для моего сайта. Это должно соответствовать следующим требованиям
- он должен управляться базой данных, извлекая данные из БД для построения структуры меню
- данные, извлекаемые из БД, должны быть кэшированы - я не хочу нажимать на БД для каждого запроса страницы
На данный момент у меня работает упрощенный пример, но я не знаю, как интегрировать кеширование. Я думаю, что мне, возможно, придется переделывать весь способ, которым я делаю это. Вот:
У меня есть ProductMenuAttribute, который извлекает данные из БД и сохраняет их в 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 и использую их для отображения моего меню. Это небольшой фрагмент моего неупорядоченного списка меню, стилизованный под 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();
}
}
Теперь всякий раз, когда выполняется какое-либо действие на моем контроллере, вызывается метод OnActionExecuted в классе ProductMenuAttribute, который устанавливает ViewData, который в конечном итоге будет использоваться на моем Site.Master для создания моего меню из БД, и в этот раз Я называю любое из действий.
Проблема сейчас в том, как добавить кеширование в этот сценарий? Я понятия не имею, с чего начать, и чувствую, что решение, которое я имею, не кешируется.
3 ответа
Я думаю, что мне действительно нужно использовать вспомогательное расширение Html.RenderAction() из проекта MVC Futures.
Идея состоит в том, чтобы использовать вышеупомянутое для вызова действия на контроллере, который сгенерирует структуру меню HTML, извлекая данные из БД. Затем я также использую простое кэширование вывода для кэширования данных на несколько минут.
Это самый простой подход, который я нашел до сих пор, чтобы достичь того, чего я хочу.
РЕДАКТИРОВАТЬ: Фил Хаак недавно написал об этом в блоге - Html.RenderAction и Html.Action. Отличное сообщение в блоге, охватывающее все мои точные потребности, с объяснением всех проблем.
Чтобы кэширование работало правильно, мне нужно поставить Html.RenderAction()
вызов внутри ViewUserControl с установленной директивой OutputCaching следующим образом:
<@ OutputCache Duration="100" VaryByParam="None" %>
Я тогда называю выше с Html.RenderPartial()
и вуаля, все работает!
Вы можете изменить свой репозиторий так, чтобы он учитывал кеш: см. Два вопроса: кэшированный репозиторий и http кеш.
Я сделал это с помощью блока кэширования Enterprise Library. Вы проверяете кэшированные данные, если нет кэшированных данных, вы создаете HTML-строку из данных в вашей базе данных и помещаете ее в кеш, чтобы позже при поиске кэшированных данных вы могли просто вывести простую строку:D
Просто упомянуть, что код для этого был в статическом классе. Я приведу пример, но я переписываю это приложение в MVC2 с нуля, поэтому у меня нет кода вручную.