Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asp.Net MVC 3 Partial Page Output Caching Not Honoring Config Settings

I have a simple partial view that I'm rendering in my main view with:

 @Html.Action("All", "Template")

On my controller I have this:

    [OutputCache(CacheProfile = "Templates")]
    public ActionResult All()
    {
        return Content("This stinks.");
    }

And in my config this:

<caching>
  <outputCacheSettings>
    <outputCacheProfiles>
      <clear/>
      <add name="Templates" duration="3600" varyByParam="none"/>       
    </outputCacheProfiles>
  </outputCacheSettings>
  <outputCache  enableOutputCache="false" enableFragmentCache="false" />
</caching>

This will fail at runtime with exception:

Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper

And inner exception:

Duration must be a positive number

Now obviously it's not picking up my web.config settings, because if I change it to:

[OutputCache(Duration = 3600)]

It will work, but also notice in my web.config I turned off enableOutputCache and enableFragmentCache, but it doesn't honor these settings.

Curiously, in a normal view these settings work fine, so what is it about partial views that is breaking this? Am I missing something? The Gu says this should work just fine... In short, is it supposed to honor caching settings in web.config and if not, why not?

like image 934
Greg Roberts Avatar asked Jan 25 '11 19:01

Greg Roberts


1 Answers

So I took a minute and looked at the MVC 3 source. The first thing that came to me was this feature seemed a bit hacky. Mainly because they are reusing an attribute that works in one situation honoring all of the properties and config settings, and then in the child action scenario just ignoring all of those settings and only allowing VaryByParam and Duration.

How one would go about figuring out what is supported is beyond me. Because the exception they want to throw that says Unsupported Setting will never get thrown unless you supplied a duration and a VaryByParam value

Here is the main piece of code that smells:

if (Duration <= 0) {
    throw new InvalidOperationException(MvcResources.OutputCacheAttribute_InvalidDuration);
}

if (String.IsNullOrWhiteSpace(VaryByParam)) {
    throw new InvalidOperationException(MvcResources.OutputCacheAttribute_InvalidVaryByParam);
}

if (!String.IsNullOrWhiteSpace(CacheProfile) ||
    !String.IsNullOrWhiteSpace(SqlDependency) ||
    !String.IsNullOrWhiteSpace(VaryByContentEncoding) ||
    !String.IsNullOrWhiteSpace(VaryByHeader) ||
    _locationWasSet || _noStoreWasSet) {
    throw new InvalidOperationException(MvcResources.OutputCacheAttribute_ChildAction_UnsupportedSetting);
}

I'm not sure why this isn't called out in documentation, but even if it was the api should make it clear, or at least throw the right exception.

In short, partial output caching works, BUTT not like you would want it too. I'll work on fixing the code and honoring some of the settings like enabled.

Update: I fixed the current implemenation to at least work for my situation with respecting the enabled flag and allowing cache profiles from the web.config. Detailed in my blog post.

like image 53
Greg Roberts Avatar answered Nov 14 '22 18:11

Greg Roberts