11

I am attempting to cache sections of a navigation menu according to different criteria.

For example, news and articles need to be refreshed on a duration basis, whereas login and profile stuff should be cached on a per user basis.

I'm considering 2 options - would anyone be kind enough to enlighten me about the pros / cons of each? And if possible suggest a better approach to take!

Option 1.

Simply cache all required html as strings in the Data Cache. Check for user differences manually when required.

I (perhaps incorrectly) imagine that this would be the most work to implement, but also the most efficient way of caching the different sections.

Option 2.

Have a NavigationController with different child action for each section of the menu. (We can apply a different outputCacheProfile on each child action as required.)

But this would require us to call a separate RenderAction for each section of the navigation menu. And I'm worried about this because of a comment on one of Phil Haack's blog posts:

[Render Action] is very similar to making another request since we need to run through routing to make sure we have the appropriate route data and context to call the action method. So each call to RenderAction is going to add up.

Full post here: http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx

Dave Alperovich
  • 32,320
  • 8
  • 79
  • 101
Martin Hansen Lennox
  • 2,837
  • 2
  • 23
  • 64
  • I really like the second option - it is very good architecture and easy to scale. Unfortunately without any information about your application load and performance requirements it is impossible to give a definitive answer what to do. First option seems to requre quite a lot of manual work and does not scale at all (if you have different kinds of users), the only reason to go that way - if rendering the menu takes at least 10% of the time to retrieve it (eg. from database). But again, without information about performance requirements it is just a guess. – Aleksei Poliakov Dec 01 '13 at 15:09
  • Thanks, and yes, agreed regarding scalability. Good point. – Martin Hansen Lennox Dec 03 '13 at 17:15

1 Answers1

5

I think there's been a general avoidance of this question because there is no right answer here.

In fact, your choice of Architecture for implementing complex navigation will determine the best Caching strategy.


I'm deeply partial to Navigation through Partial Views with Child Actions.

I agree with you that referencing files is more work. I prefer to have database entries with navigation options grouped by keys and referenced by argument to child actions.

So your Navigation Table may look like this

grpId    Title        Path
1        Home Page    /
1        About Page   /Home/About
1        Reports Page /Reports
2        Home Page    /
2        Admin Page   /Admin
2        Reports Page /Reports

and your child action would take a grpId

[OutputCache(Duration = 60000, VaryByParam = "grpId")]
public PartialViewResult NavigationPage(int grpId)

could pull all your navigation group options and render a custom navigation menu. This form of output cache is customized by time (60000 secs and your param)


Conclusion:

I suspect I have told you nothing new, but have only confirmed what you were already leaning toward. The MVC framework is very robust and provides tools to handle nicely what you want to do. Using files and Data Cache is also a valid method, but it would be greater head-ache and work on your part to implement.

Keep in mind: Haacks's post is over 4 years old (MVC 2 Beta) . The framework and output cache has evolved nicely since then. You can now Cache Partials without worrying about caching the entire page. This recent reference to caching with MVC 4 doesn't speak directly to Phil's earlier concerns, but notably neglects them.

Dave Alperovich
  • 32,320
  • 8
  • 79
  • 101
  • HI Dave, thanks for your response and examples. I do like the db idea, but unfortunately it is too late to implement at this stage. I admit that the post was old. To me his wording suggested that that each call to a Render Action was not unlike a full page request. Serving up the equivalent of 5 pages for each time a single page is called still sounds scary to me. – Martin Hansen Lennox Dec 03 '13 at 17:12
  • This is part of a small module that will be rolled out to a large number of sites (with widely varying loads), so I wanted to get it as performance friendly as possible, even though it might involve more work. Looks like there's no general consensus on this, so testing is the way to go. – Martin Hansen Lennox Dec 03 '13 at 17:12
  • @MartinHansenLennox, it's partly true that each partial is like a sub-page. But the framework is very intelligent. Each partial does not use an entire http request cycle, thereby, most of the overhead is missing. They are really no more stress than instantiating an extra controller, runnning actions method. – Dave Alperovich Dec 03 '13 at 17:31
  • Ok, that's good to know. I got the opposite impression, but through my ignorance I am easily misled. :) – Martin Hansen Lennox Dec 03 '13 at 18:40