Custom OutputCache provider generates different keys on Add() vs Set()

787 views Asked by At

I'm writing a custom OutputCacheProvider in MVC3.

The calls get fired in this order: Get, Add, Set. I expect that in all methods, the keys generated will be the same, but they're not. The problem is that in the different calls Get and Add are called with a different key than in the Set method.

My request looks like this: http://localhost/testCall?startIndex=0&maxResults=25&testParam=4

With the VaryByParam set, I would expect the key to be unique based on my query params to look something like: testCall?startIndex=0&maxResults=25&testParam=4

Instead, on the Get/Add calls, the key just has the full path name: localhost/testCall

But, on the Set call, the key actually looks to do what I expect: local/testCallHQNmaxresultsV25NstartindexV0NtestparamV4FCDE

Here's my controller method.

[OutputCache(Duration = 15, VaryByParam = "*")]
public ActionResult TestOutputCache()
{
    var obj = new List<string>() {"test", "one", "two", "three"};
    return Json(obj);
}

Here's my Custom OutputCacheProvider

public class MemcacheOutputCacheProvider : OutputCacheProvider
{
    public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
    {
        base.Initialize(name, config);
    }

    public override object Get(string key)
    {
        // UNEXPECTED, the key = "localhost/testCall"
        return null;
    }

    public override object Add(string key, object entry, DateTime utcExpiry)
    {
        // UNEXPECTED, the key = "localhost/testCall"
        return null;
    }

    public override void Set(string key, object entry, DateTime utcExpiry)
    {
        // EXPECTED, the key = "local/testCallHQNmaxresultsV25NstartindexV0NtestparamV4FCDE"
    }

    public override void Remove(string key)
    {
    }
}   

If the Set call is made with the correct params, but the Get() is never called with the correct key, then the caching will only work on the root call of /testCall

2

There are 2 answers

0
netanel elipaz On

The key parameter on your implementation of the Set method is encoded, you should decode it. you can use HttpUtility.UrlDecode method.

   public override object Add(string key, object entry, DateTime utcExpiry)
        {
            var decodedKey = HttpUtility.UrlDecode(key)
              // implement your caching logic here 
            return entry;
        }

The Key parameter will always come in the Set Method with additional parameters - this is normal.

0
MatthewT On

The OutputCacheProvider uses the CreateOutputCachedItemKey method that is defined here: https://github.com/microsoft/referencesource/blob/a7bd3242bd7732dec4aebb21fbc0f6de61c2545e/System.Web/OutputCacheModule.cs#L129

If you read through the code of that method you can see how it assembles the key, which explains the extra letters and query string items in your key.