CacheAdapter–Now a Nuget package

Published Tuesday, May 31, 2011 5:12 PM

Note: Link to Wiki is here

A while ago, I blogged about a personal project around caching that allowed you to abstract away the underlying cache mechanism, and use whatever cache you wanted. Through simple configuration, you can choose to use either the memory cache provided by System.Runtime.Caching in .Net 4, the traditional ASP.NET web cache, or you can use the Windows AppFabric caching to taker advantage of distributed caching.

Well, its now a package on Nuget that you can easily install and use immediately. You can grab it from here.

install-package-image

Update: This package uses the Microsoft Public Licence (MS-PL).

Just as a recap, you can use this cache adapter like this:

var data1 = cacheProvider.Get<SomeData>("cache-key", DateTime.Now.AddSeconds(3), () =>
{
    // This is the anonymous function which gets called if the data is not in the cache.
    // This method is executed and whatever is returned, is added to the cache with the
    // passed in expiry time.
    Console.WriteLine("... => Adding data to the cache... 1st call");
    var someData = new SomeData() { SomeText = "cache example1", SomeNumber = 1 };
    return someData;
});

(Note: You will get a small example .cs file included in your project that contains this example usage when you install the package)

You can see in the example, that you can request the data, and provide a lambda that retrieves that data if its not in the cache. The data gets added to the cache once the lambda has been executed to retrieve the data from the source. Also, the data that is returned is strongly typed. It is not a generic object that you then need to cast.

Additionally, you can set the type of cache used by one line of configuration:

<setting name="CacheToUse" serializeAs="String">
    <value>Memory</value>
</setting>

If I wanted to use the ASP.NET Web cache, I could simply set the config item like so:

<setting name="CacheToUse" serializeAs="String">
    <value>Web</value>
</setting>

And if I wanted to use the AppFabric distributed cache (assuming it has been installed on the system), then I can simply set the config like so:

<setting name="CacheToUse" serializeAs="String">
    <value>AppFabric</value>
</setting>

The package references the required AppFabric client assemblies for you. This means you can write a web application today using this package and use the traditional ASP.NET cache. Then we you are ready, install AppFabric, setup a cache cluster, change the configuration to enable AppFabric and you are away. No code changes to your app.

Using AppFabric

To use AppFabric, there are a few extra things to do by way of Infrastructure. Obviously, you need to download and install it. Then you need to setup your cache cluster via the wizard when you install it (or via powershell if you choose). During this process you will be creating some cache nodes and you need to create a named cache for your application. This can be done via powershell using the

  • New-Cache {cachename}

powershell command. In addition, you will need to ensure that the user that will be accessing the cache has access to it. Again, this can be done from powershell via the:

  • Grant-CacheAllowedClientAccount {account}

There is some additional config you will need to do as well. In the application config file you will need to change the following entries to match your configured infrastructure:

<setting name="DistributedCacheServers" serializeAs="String">
    <value>localhost:22223</value>
</setting>
<setting name="DistributedCacheName" serializeAs="String">
    <value>MyCache</value>
</setting>

The “DistributedCacheServers” setting can be a comma separated list of servers and ports that the cache client (ie. your app) will communicate with. This can be one or as many comma separated entries as you like and depends on your cache cluster config.

The “DistributedCacheName” is the name of the cache you have setup in the cache cluster for your app. (Detailed above)

Final Notes

Before I published this package, I cleaned it up a bit as I have been using it on a current project and I didn’t like a number of ways I implemented things initially. Instead of multiple assemblies, everything is in the one assembly.

Also, I removed the use of Unity as a mechanism for dependency injection and implemented a very very simple method which uses no particular dependency injection implementation. I did this because everyone wants to do DI (Dependency Injection) using their favourite implementation whether this be Unity, Autofac, Ninject, Castle Windsor etc. etc. So I opted for something that does the job, it is not what a purist would be happy with, but is dead simple to rip out and change which is what I expect most people would do.

Finally, because all cache access is via an interface, it allows for easy testability.

So go grab it. Or you can download the source code form here and change it to your hearts content. Its actually a relatively simple implementation and it would be easy to plug in any underlying cache implementation should you wish.

by Glav

Comments

# raf sistemleri said on Tuesday, May 31, 2011 8:07 AM

Thanks for sharing.

# Flalar said on Tuesday, May 31, 2011 9:01 AM

I tend to prefer HttpRuntime.Cache over System.Web.HttpContext.Current.Cache. If you’re not in an environment where HttpContext doed not exist it will not throw errors rather return cache misses

# F. Morrison said on Tuesday, May 31, 2011 1:52 PM

Why would I want to switch from using the Microsoft recommended Enterprise Library 5.0 Caching Application Block to this new method, losing the synergy of Microsoft Enterprise Library along the way?

# Joe Audette said on Tuesday, May 31, 2011 2:41 PM

This looks well done and very useful!

I'm interested in using your CacheAdapter in my own projects but wonder what is the license?

It is difficult to use something without an explicit license, hopefully something very permissive like MsPl or Apache or MIT or BSD.

Could you clarify this? Sorry if you already have this information somewhere and I've missed it.

Thanks!

# Glav said on Tuesday, May 31, 2011 6:24 PM

F.Morrison,

EntLib caching block is just an option and one you can plug-in to this code base easily. ASP.NET Web cache (IMHO) is far superior to EntLib caching and I dont want to introduce dependecies to Entlib if I dont have to. Switching then to an even more powerful caching mechanism such as AppFabric is just some config changes. No code change but still taking full advantage of distributed cache farms, something Entlib caching cannot do. In addition, Entlib caching utilises a different syntax. This library removes that and provides a thin consistent layer between code and cache.

# Glav said on Saturday, June 4, 2011 12:40 AM

Hi Joe,

I have updated the post to include the licencing information. It is distributed under the Microsoft Public Licence (MS-PL).

# Mandeep said on Tuesday, June 14, 2011 4:27 PM

i think you should also add Add() or Set() methods in Icacheprovider because some times we only want to add data otherwise we have to fetch data to insert it into cache. I hope u got it what i'm saying.

btw great work. Keep helping the community.

Thanks.

# Mez said on Friday, May 11, 2012 3:34 PM

How hard would it be to convert this into a EF provider?

# Glav said on Friday, May 11, 2012 11:33 PM

I would imagine quite easy. The code is not very complicated and it is just an interface based approach. It is not something on my horizon tho, but you could fork the codebase and go for it.

# thiet ke website said on Tuesday, June 5, 2012 11:29 AM

How to clear cache when using this cache adapter. Thanks

# cmsmart said on Friday, March 1, 2013 3:44 AM

One Page Check Out for Virtuemart plugin - no HACK, 100% AJAX, Compatiple with Virtuemart 2.0.x

All Virtuemart site need One page checkout to make the check out process as simple as possiple while remain the powerfull function your payment and customer information.

# Mikhail said on Friday, June 21, 2013 1:04 PM

Seems to be a good idea, but implementation looks incomplete.

1) Having all cache adapters in 1 assembly resulted in unused references (for example - if I'm using memcached I don;t want to see references to AppFabric)

2) Implementation of AddToPerRequestCache in AppFabric and Inmemory cache is completely incorrect:

this.Add(cacheKey, TimeSpan.FromSeconds(1.0), dataToAdd);

It could be useful to introduce some Scope object to allow using this method for WCF requests for example

# Glav said on Saturday, June 22, 2013 9:05 PM

thiet ke,

It is currently not possible to clear the entire cache programmatically using this package. Only individual items. Pls add this as a feature request to the BitBucket repo and I'll attempt to get to it.

# Glav said on Saturday, June 22, 2013 9:07 PM

Hi Mikhail,

Thanks for the comments, in response.

1. The assembly references are necessary to get it to compile, otherwise I'd have to conditionally remove code and that defeats the whole purpose of then being able to switch providers via config as it would then require re-injection code. overall its a pretty minimal price to pay.

2. This has been completely re-written in the latest code base. The nuget package has not been updated yet as I am working on some larger scale changes that goes with it.

# Louis said on Wednesday, July 10, 2013 8:48 AM

Hi Glav!

So I'm in the process of implementing a web app that uses the cache adapter in "Memory" mode. We're trying to put into a recently created web farm that uses a clusterd AppFabric cache. I've changed the CacheToUse to "AppFabric", added the two cache servers "Server1:22233;Server2:22233", and entered the created cache name in the "DistributedCacheName".

The app crashes though with the error "The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters." It looks like the part the kills it is "Microsoft.ApplicationServer.Caching.ClientAcsSecurity.ParseAcsConfig(authConfigEncoded As SecureString)" The account that the apppool runs under has rights to the cache. I'm not entirely sure where the authenication bit is coming into play.

Any help would be awesome!

# Glav said on Wednesday, July 10, 2013 5:17 PM

Hi Louis,

The problem will be related to config, specifically the

MessageSecurityAuthorizationInfo entry in the CacheSpecificData section. It seems like its not a valid key and might be missing a character or something like that.

You can contact me on glav AT theglavs.com and I'll be happy to help.

Leave a Comment

(required) 
(required) 
(optional)
(required) 

This Blog

Syndication