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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With