ASP.NET MVC output cache with dynamic fragment
Asked Answered
C

5

9

How could I cache an entire page except a bit at the top which says something along the lines of "Welcome back, Matt! | Log Out" if the user is logged in and so-on?

I'm using ASP.NET MVC 2.

Cupel answered 26/7, 2010 at 22:5 Comment(3)
This is sometimes called "donut caching" and is not supported in asp.net mvc 2 https://mcmap.net/q/1317058/-donut-caching-asp-net-mvc2Epistemology
Why? o_O Are there no other feasible solutions?Cupel
I haven't seen an implementation of donut caching. You can always cache the data in the controller, instead of caching the html output.Stonybroke
S
6

What you are trying to achieve is called donut-caching or cache substitution. As of ASP.NET MVC 2 there is no built in helper to support this scenario. As much as I know it was a planned feature in MVC v.1 but it was dropped somewhere in the way to the release. For more info check this links http://haacked.com/archive/2008/11/05/donut-caching-in-asp.net-mvc.aspx, Is Donut Caching working properly with ASP.NET MVC?. VaryByParam option that is mentioned by Oleg here is not a good idea in your case. If you have VaryByParam a different version of the page will be put in the cache for every different value of the parameter (in your case for every user-name). Personally I would think of caching the data, not the whole output of the page.

Stonybroke answered 30/7, 2010 at 13:4 Comment(0)
Q
3

Probably helps

<%@ OutputCache Duration="15" VaryByParam="*" %>

or with some other value for the VaryByParam. See http://msdn.microsoft.com/en-us/library/hdxfb6cy.aspx, http://blog.maartenballiauw.be/post/2008/06/Creating-an-ASPNET-MVC-OutputCache-ActionFilterAttribute.aspx and http://blogs.microsoft.co.il/blogs/gilf/archive/2010/07/18/asp-net-output-cache-provider.aspx.

Moreover, if you have the start page which is not user depended, it is possible to replace the start page with a very static welcome page with the empty field (hidden div) instead of "Welcome back, Matt! | Log Out". After that an ajax request for filling of the user name can be started at the client side. This kind of the welcome page page can be very good cached.

Quaggy answered 29/7, 2010 at 17:29 Comment(4)
In Matt's case this means that a separate version of the page will be put in cache for every value of the parameter(every user-name in his case).Stonybroke
Good point, although retrieving the username via ajax is an interesting idea. I could also try retrieving the username from a cookie, to prevent making an extra request to the server.Cupel
I thought one must avoid the OutputCache page directive in MVC application and use action filters instead. :SArgil
@Robert How would you use action filters to implement this?Hydroelectric
M
0

Here you have a workaround solution:

*Add the OuptutCache attribute to the Controller that manages the whole view as usually:

[OutputCache(Duration = 3600, VaryByParam = "*")]
public ActionResult Index(FormCollection formCollection)
{
   //Controller code
}

*For the part that you don't want to do caching, load it using jquery + an ajax request (with its own controller and without the OutputCache attribute):

<div id="loginContainer"></div>

$(document).ready(function() {

    $.post('controller/action', postdata, function(data) {

    if (data.success == true) {

        //Populate the container with the obtained data
    }
    });

});

The view will be retrieved from the Output Cache and, once it is loaded, a request to obtain the login info will be performed. Hopefully, it will be a very quick request and the user will not notice the delay.

Misshape answered 4/8, 2010 at 10:30 Comment(1)
And what happens when JavaScript is disabled on the client?Dilatometer
H
0

Get this via nuget: http://mvcdonutcaching.codeplex.com/

Add an action for LogOnPArtial, so you can change it from Html.Partial to Html.Action in the _Layout.cshtml

@Html.Action("_LogOnPartial","Account",true)

The true is a exclude parameter that says, exclude this from caching. The action will be called even if the page it is in is cached. This is the "hole" in the donut that is not cached.

On your page, such as About.cshtml that you want cached, apply DonutOutputCache attribute. This allows the new framework to inspect the page as it's caching it, and add flags where you've excluded actions.

The nice thing is the _LogOnPartial is not cached and will refresh for different users while the rest of the page is cached and the About() action will not be run. You could even configure caching on the _LogOnPartial action you created using the DonutOutputCache attribute, but a more frequent or less frequent interval, or vary by some other param. This allows you to compose pages of partials, and the cache refreshing logic is independently configured for each partial.

IMO this tool is exactly how I imagined caching in MVC should have been implemented.

Hydroelectric answered 23/8, 2012 at 20:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.