views:

214

answers:

2

I am attempting to write a common "menu.ascx" usercontrol in Asp.Net MVC that will generate a properly formatted HTML menu for my application. The menu is generated based on content in the database and a series of Resource resolutions... which are passed to the PartialView through an attribute on a ViewModel.

It would make sense to utilize an OutputCache directive on the menu.ascx control in order to limit the number of round-trips to the database and Resource files. My intention is to mark the OutputCache directive with VaryByParam=none and VaryByCustom attributes, implementing a custom security lookup in global.asax...

My question is: how do we know when the OutputCache for menu.ascx is going to be used, so that we can skip the data fetch operations when constructing the ViewModel in the controller?


Some sample UserControl code:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl"  %>
<%@ OutputCache VaryByParam="none" VaryByCustom="customstring" %>
<ul>
<% var model = (IMyViewModel)Model; 
 foreach (var menu in model.Menus) { %>
   <li><a href="<%= menu.href %>"><%= menu.Text %></a></li>
<% } %>
</ul>
+1  A: 

Here's interesting readin on that subject Donut Hole Caching in ASP.NET MVC and here ASP.NET MVC Result Cache , I would basically do this menu by RenderAction method in master page to invoke action which will pull data from database and theb , and then cache the action result

Tadeusz Wójcik
RenderAction is only available in ASP.Net MVC futures... I'm not sure if we want to go there yet.
Jeff Fritz
A: 

I think I have found a suitable workaround to my problem.

In the Menus property getter for my concrete ViewModel implementation, I am writing proxy code to reach back into the instantiating Controller and request the Menu data. In this way, I can create the Menu data on-the-fly, when the PartialView requests it. If the PartialView is coming out of the OutputCache, the Menu property will not be requested.

So, my IMyViewModel looks a little like this:

public interface IMyViewModel {

  IEnumerable<Menu> Menus { get; }

  ///<summary>
  /// A pointer back to the calling controller, which inherits from the abstract MyBaseController
  ///</summary>
  MyBaseController Controller { get; set; }

}

and my concrete implementation of Menus looks a little like this:

public IEnumerable<Menu> Menus 
{
   get { return Controller.GetMenus(); }
}

Comments? Is this a viable solution?

Jeff Fritz