April 04, 2015

Implementing Caching Framework for SharePoint 2013 Farm Applications

In this blog I am going to share my experience about implementing caching framework for Sharepoint 2013 Farm Applications using AppFabric cache system with a real example.

First of all, I highly recommend you to see a video course on pluralsight website named: Caching in the .NET Stack: Inside-Out. It can help you to have a comprehensive overview about caching strategies and different ways of it’s implementations.

I assume that you have a farm application project in sharepoint 2013 which is using Microsoft Unity for repository layer, and you want to add a data caching functionality to the repository. It means you are using Microsoft Unity as a dependency injection container and you are rely on interfaces rather than concrete classes. In addition I have to mention this notice that multibranding is playing vital role in your application.
Ream more repository pattern: The Repository Pattern, And also read about Unity.

As you may know, SharePoint is a distributed framework which is regularly hosting on different servers. Obviously to overcome all difficulties with regard to managing and maintaining the distributed cache, we need a suitable cache system like AppFabric that is being installed with sharepoint core. you can read more about AppFabric Cache in this article: SharePoint 2013: AppFabric and Distributed Cache Service

For implementing caching framework, we have to treat this task as a cross cutting concern and the best way to implement crosscutting concerns is Aspect Oriented Programming(AOP).
To review what are cross cutting concerns and AOP you can review these pages of Microsoft: Crosscutting Concerns , AOP
Briefly I should mention that we are going to implement the caching framework without changing our infrastructure or classes by using unity interceptor.  

Download TestCaching project from github and open it in Visual Studio 2012. The solution of TestCaching is involved there projects:

1- Caching Project: All the classes related to caching are located inside.
2- DataAccess Project: Simulates your data access or repository layer which used Microsoft Unity container to create and inject classes.
3- TestCaching Project: Could be the consumer layer in your real application. 

First of all I want to draw your attention to the most important class in the caching project named: CachingInterceptionBehavior. In fact, by adding this class and putting in the web config for each specific Interface, on executing of each method of interface, we will receive an event to do whatever we want. It means on each function calling, the Invoke method of CachingInterceptionBehavior will be called, so in this place we can look through the cache system and if the value of the current function is already existed, return that otherwise the real function is being called and the result is being put in AppFarbic cache. 

let’s take a look at some important parts of CachingInterceptionBehavior and explain them:

1- CacheConfiguration: by using this class you can put some general setting inside the web config. I put the Enable/Disable option in the web config already.

    if (!CacheConfiguration.Current.Enabled)
        return Proceed(input, getNext);

2- NoCacheAttribute: For some functions we may want to ignore caching at all. this attribute has been implemented for this facility. 

    var nocache = input.MethodBase.GetCustomAttributes(typeof(NoCacheAttribute), false);
    if (nocache.Count() != 0)
        return Proceed(input, getNext);

3- AppFabricCache: This singleton class which has been wrapped by Cache class is the main location of handling and managing cache key and value. The most important object inside this class is DataCache that is part of  Microsoft.ApplicationServer.Caching dll. This dll is responsible to communicate, save and restore cache value to the AppFabric cache system. 

    var cache = Caching.Cache.AppFabric;
    if (cache == null)
       return Proceed(input, getNext);

4- Avoid caching Void functions: Void functions regularly doing some logics in softwares. These logics can be business rules, web services and etc. Generally we must to ignore caching all void methods to prevent inconsistency in our business logics.

5- Generate proper key for functions(Caching Strategy):  How we are caching the data?
In order to cache the result value of each function, we put the return value in the cache system, and when that specific function will be called for another time, rather than executing the body of method, cache value will be returning back.

Suppose that we have these functions in the repository layer. 

        GetPerson(Id), GetPerson(Name,Family)

Needless to say that by using the method name it is not possible to save and retrieve the correct value of functions. in this case GetPerson(1) and GetPerson(2) will always return the same value which is totally incorrect. To prevent this situation, and to generate a unique key for each function, we are generating an unique key by concatenating MethodName and it’s parameters.

        Cache Key:  MethodName + Param1 + Param2 + . . . + ParamZ       

For having a short and predictable key, all things you need is a hash value which returns a short string sutis to use as a CacheKey. 

6- Cache Expire Strategy by Implementing Regions:

On the most important topic in the caching system is Expiration Strategy which means, when exactly we should expire a cache value of functions. Assume that some information of a person has been changed, so rather than retrieving the cache value for that person we should again call GetPerson method and put a new value in cache. 
In the past I wrote an article about this topic that I recommend you to read it. Expiration Of Cache Values For Dependent Objects
    Step1: Create a Region: 
    For each Interface I have created a region as you can see below:

         Region = SPContext.Current.Site.ID + InterfaceName         

It means all the functions of each interface for each SharePoint web application is going to be located inside a unique region. Actually by considering SiteId the multi branding (multi tenanting) of Sharepoint farm applications will be supported. 

     Step2: Create Cache Expire Attribute:

For example, when a function named EditPerson() is calling, it should expire all relative functions regarding to GetPerson(). So after calling EditPerson() the value of GetPerson should be expired. To implement this functionality I have created an attribute named: ExpireCacheAttribute

    public class ExpireCacheAttribute : System.Attribute
      public Type[] Regions { get; set; }

This attribute has an array of type which represents all regions that are going to be expired. Each function that causes some expiration of values should implement this attribute. 

For example:
    [ExpireCache(Regions = new Type[] { typeof(IPersonInfo), typeof(IPersonProduct)})]
    void EditPerson(Person person);    

By implementing this attribute, after calling EditPerson, all cache values of methods inside the IPersonInfo and IPersonProduct will be expired. 

7-  Support multi branding (multi tenant): 

If you have some functionalities in the Central Administration website, for example managing basic information like groups or user, so by doing some changes, the cache value of all tenant should be expired and re-fetch data from database.

In this case we need to understand whether the current website is running the code is Central Administration website or not? If it is, we need to expire all the regions for subsites in Sharepoint Central Administration. 

In addition, by changing the AppFabricCache.cs implementation with another caching system, you can easily use this framework for other types of project like ASP.NET or ASP.NET MVC applications.

I hope this blog could be helpful for you and I will be waiting for your opinion about that. 

Source Code: Caching Framework for SharePoint 2013 Farm Applications