WCF AppFabric Caching Caching Sample Behavior

On Thanksgiving day while I was running in the snow I had an idea – what if you could create an Operation Behavior that would allow WCF to cache the result of a service call in Windows Server AppFabric Cache?

Download WCF AppFabric Caching Caching Sample Behavior

So I created a sample application that does this by implementing an attribute that implements IOperationBehavior and IOperationInvoker along with a Service Behavior that supports AppFabric Caching.  I wanted to make this work with AppFabric Caching but not require you to to have AppFabric caching running when developing or testing the service. The solution I came up with was to look for a Service Extension that implements IServiceCache.  If I find it, I use it.  Otherwise I create a local cache using System.Runtime.MemoryCache.

Get Microsoft Silverlight

To ask for caching on a service you can either add it to your contract or request it in config.

    [ServiceContract]
    public interface ISampleService
    {
        [OperationContract]
        [CacheResult(Minutes=2)]
        SampleData GetSampleData(SampleDataRequest request);
    }

To request caching in your config

<system.servicemodel>

    <extensions>

      <behaviorextensions>

        <add type="Microsoft.ServiceModel.Samples.Caching.AppFabric.AppFabricCacheElement, Microsoft.ServiceModel.Samples.Caching.AppFabric, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="appFabricCachingBehavior" />

      </behaviorextensions>

    </extensions>

    <behaviors>

      <servicebehaviors>

        <behavior name="">

          <servicemetadata httpgetenabled="true" />

          <servicedebug includeexceptiondetailinfaults="true" />

          <appfabriccachingbehavior />

        </behavior>

      </servicebehaviors>

    </behaviors>

    <servicehostingenvironment multiplesitebindingsenabled="true" />

  </system.servicemodel>

Check it out

The sample includes unit tests that demonstrate how you can setup parameters for cache keys and complex types. Hope you like it!

Comments

  • Anonymous
    December 16, 2010
    Hi Ron, haven’t looked at your code yet, but that’s exactly the same idea I had a while ago, when I was reasoning about caching in wcf, with one of my customers. I’d like to make a couple of points though, about the solution:
  1. I think the configuration based approach should be removed. The reason I say so, is because caching an operation result makes sense only for operations that have “Read” semantic and no side effects, (much like a correct implementation for an Http Get in a RESTfull scenario). The attribute approach is therefore the preferable one, because makes caching an “Opt-in” option for your service operation. Enabling caching at the configuration level can still be considered an option for RESTfull services. In such a scenario I suggest to turn the service behavior in an endpoint one, and have it enabling caching only for HttpGet methods.
  2. Finding a uniform way to compute the cache key, based on operation parameters is not easy in the general case (as I said I did not look at the code so I don’t know how you solved the problem). What do you think about it? Thanks Antonello Tesoro
  • Anonymous
    December 17, 2010
    Thanks for your feedback.  This was an interesting experiment to see what could be done.  I agree you have to be careful with your caching strategy.  I pursued the Config option because I wanted to see if I could make it work with WorkflowServices but in the end calculating the cache key proved to be too difficult so I gave up on it.

  • Anonymous
    December 17, 2010
    Thank you, for your answer. By the way, I'm curious about the idea of integrating this solution with WF services, given that WorkflowServices runtime need its own specialized operation invoker, which I believe cannot be replaced. The WorkflowOperationInvoker is implemented as an inner class of the WorkflowOperationBehavior so, there's no way to inherit from it. The class also implements 2 internal interfaces (IManualConcurrencyOperationInvoker and IInstanceTransaction), thus no hope for encapsulation (the outer operation invoker should be able to reimplement those interfaces). If you have any ideas on how to overcome those issues (or if I’m wrong in the point I made), please let me know. Thanks again. Antonello

  • Anonymous
    December 17, 2010
    Great question - rather than discuss this on the blog I suggest you ask your question on the WF forum social.msdn.microsoft.com/.../threads

  • Anonymous
    December 24, 2010
    Nice ripoff Ron ;) blogical.se/.../use-appfabric-cache-to-cache-your-wcf-service-response.aspx I'm just kidding, but the posta are quite similar...

  • Anonymous
    December 25, 2010
    Wow - his post is better than mine.  I guess great minds think alike :-)