How to implement VaryByCustom caching?

2019-04-19 03:40发布

问题:

I'm trying to implement functionality to cache certain pages depending on the host. This is because I can have multiple versions of a page which have the same parameters, and where the only difference in terms of a request is the host that is being requested.

So, for example these two URLs will request the same page, but they are styled differently:

http://www.a.com/something/specific

and

http://www.b.com/something/specific

I'm going through the example outlined here:

http://msdn.microsoft.com/en-us/library/5ecf4420%28v=VS.90%29.aspx

but it's not making sense to me.

I've added this to my global.asax:

public override string GetVaryByCustomString(HttpContext context, string arg)
{
    if (arg == "host")
    {
        return "host=" + context.Request.Url.Host;
    }

    return base.GetVaryByCustomString(context, arg);
}

and the example states "To set the custom string programmatically, call the SetVaryByCustom method and pass it the custom string to use", with code similar to the following:

Response.Cache.SetVaryByCustom("host");

The problem is I'm not sure what to do with this. I've added the previous line to MvcApplication_EndRequest because it seems like it makes sense, but I don't think this is right because when I set breakpoints in GetVaryByCustomString they never get hit.

Can somebody please tell me what I'm missing here? Or if I need to do this differently?

Edit: RE Darin's answer below, I'm already decorating my actions with:

[CustomOutputCache(CacheProfile = "FundScreener")] // or similar depending on the action

where CustomOutputCacheAttribute is defined as:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CustomOutputCacheAttribute: OutputCacheAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        AddLabelFilesDependency(filterContext);
        base.OnResultExecuted(filterContext);
    }

    private static void AddLabelFilesDependency(ControllerContext filterContext)
    {
        IConfigurationManager configurationManager = ObjectFactory.TryGetInstance<IConfigurationManager>();
        if (configurationManager == null 
            || filterContext == null 
            || filterContext.RequestContext == null
            || filterContext.RequestContext.HttpContext == null
            || filterContext.RequestContext.HttpContext.Response == null
            )
        {
            return;
        }
        string[] files = Directory.GetFiles(configurationManager.LabelsDirectoryPath, "*.xml");
        foreach(var file in files)
        {
            filterContext.RequestContext.HttpContext.Response.AddFileDependency(file);
        }
    }
}

where the profile is defined as:

<add name="FundScreener"
     location="Server"
     enabled="true"
     varyByParam="*"
     duration="1200"
     sqlDependency="mmftms:offline.ScreenerData"/>

Do I need to change this?

回答1:

You don't need to call SetVaryByCustom in MVC. You could use the OutputCache attribute. Checkout the following blog post.



回答2:

If you want to have different cache for different hosts, you can use:

VaryByHeader="host"

Because, that would make it use the value of header "host" in the request to vary the cache. You can add this in the OutputCache directive on your controllers/actions, or you can specify it globally in your web.config probably.

a host header will always be present if you use host-bindings, which seems to be the case for you.



回答3:

GetVaryByCustomString(...) is called by the caching layer per request and you have an opportunity to inspect the request and the passed-in argument to decide how to "categorize" this request. So if you set the VaryByCustom property/attribute to "host", you would then write code inside GetVaryByCustomString function which returns the host (as in your example, above). If the caching layer finds that it has already cached the argument "host" with the value you've returned then it will return the cached response, otherwise it executes the request and adds it to the cache.



回答4:

Based on your edit, add VaryByCustom="host" to your FundScreener output cache profile.