11
votes

With the [OutputCacheAttribute] in ASP.NET MVC 3, you can output cache with a good deal of flexibility. It's useful to leverage the 'VaryByHeader' property to bucket caching by host name. For example:

[OutputCache(Duration = 60, VaryByHeader = "host")]
public ActionResult Foo()
{
    return this.View();
}

However, on child actions, you cannot apply the 'VaryByHeader'. The framework throws the following exception:

OutputCacheAttribute for child actions only supports Duration, VaryByCustom, and VaryByParam values. Please do not set CacheProfile, Location, NoStore, SqlDependency, VaryByContentEncoding, or VaryByHeader values for child actions.

My question is, why?

Is the reason why we cannot VaryByHeader in a child action because it would provide a conflicting variance, since the parent action might have specified a different VaryByHeader value?

If I want to cache child actions differently based upon hostname, what does this mean, and how would I go about it?

1
Just curious, do child actions cause another HTTP get? Maybe the designers of this thought that since there is no second post back there would be no need to cache by different http headers. - Davin Tryon
No, child actions are just an abstraction within the same request. - dreadwail

1 Answers

13
votes

VaryByHeader affects the actual HTTP Response headers; so you're probably correct that the MVC team blocked this to prevent conflicts with the parent action.

To cache based on hostname, couldn't you use VaryByCustom? Something like (disclaimer: haven't tried this at all):

[OutputCache(Duration = 60, VaryByCustom = "host")]
public ActionResult Foo()
{
    return View();
}

followed by (in your Global.asax.cs)

public override string GetVaryByCustomString(HttpContext context, string arg)
{
    if (arg == "host")
    {
        return context.Request.Headers["host"];
    }

    // whatever you have already, or just String.Empty
    return String.Empty;
}