Building SharePoint provider hosted apps we often come across scenario which require to provision SharePoint artefacts to host web and clean up once app is un-installed, obvious choice is to go with App events. I'm not going to bore your with how to create it there are tons of documentation available out there. Before we talk about "retry mechanism" let's do a quick re-cap so that we all are on same page.
App Event Receivers are implemented as WCF service deployed to remote web-application (ASP.NET MVC/Forms) which are called by SharePoint when app is installed/un-installed/upgraded. Imagine you have to provision quite a lot of artefacts perform certain validations this is quite a bit of task, and remember we are communicating back to SharePoint Host Web using Managed Client Object Model which is again a REST call under the hood, so all operations are happening asynchronously.
You implement all the logic and configure required permissions for App to create artefacts on Host Web while debugging App Installation you notice that App Install event is called repeatedly and it again attempts to create the same artefact you already created, don't think that you forgot to configure you app properly or your app install event is behaving in weird fashion, its actually by design (read: Installing apps for SharePoint : Notes Section)
Sometimes a temporary loss of a network connection can block installation. If installation fails for any reason, the installation infrastructure will retry three times. If it does not succeed, an indication of the failure appears in the UI. Users can retry the installation later.
Cool, now that you know the reason behind "retry" let's discuss the probable solutions to handle this. The obvious way would be to keep a track of installation/un-install progress is to make use of persisted store and check the next time the "Installation Infrastructure retries". Let's explore the options for persisted store.
- App Web Property Bag
- SQL Store
- File System
App Web property bag is a decent store, since during install event you have access to App Web Property bag (note: you cannot make changes to host web property bag (Tried With SiteCollection Manged rights)), this is still decent but not optimal as you have to make additional REST call to App Web which to perform CRUD operation on Web Property bag. This technique works fine when you work with Install Event, but as you apply the same technique to Un-Install event your code will *break* because by design when the app is removed it deletes the associated App Web and hence you don't have the App Web Property Bag to store the un-install progress information.
So what next, SharePoint List is again a decent option but it has to be on Host Web and will not be fast and high performing.
As we talk about performance "Caching" comes to our mind, but before you start using your favourite search engine, please read (Caching Support for WCF Web HTTP Services). I attempted to configure the Basic Web Http Service Caching and I was not able to deploy my App. So I had to rule out this option and had to fall back on App Web Property Bag, but was a partial implementation.
Later I thought of configuring external Caching and utilize Azure Managed Cache Service this gives a flexibility to come around the situation to Configure my WCF service for Caching and utilize external store. By this mechanism I was able to properly keep track progress of Install/Un-Install events.
Azure Managed Cache Service is great, but I wanted something really simple coz I don't need a full blown distributed caching service just to keep progress!!!!
This is great but my quest for making it lighter and configuration free made me to look out for another optimized cache store, and finally my search ended at "ObjectCache and MemoryCache" these master pieces resides in "System.Runtime.Caching.dll" a quick note below (taken from links)
The MemoryCache class is similar to the ASP.NET Cache class. The MemoryCache class has many properties and methods for accessing the cache that will be familiar to you if you have used the ASP.NET Cache class. The main differences between the Cache and MemoryCache classes are that the MemoryCache class has been changed to make it usable by .NET Framework applications that are not ASP.NET applications. For example, the MemoryCacheclass has no dependencies on the System.Web assembly. Another difference is that you can create multiple instances of the MemoryCache class for use in the same application and in the same AppDomain instance.
System.Runtime.Caching.dll allows you to cache across all .Net apps, not just the IIS worker process.The highlighted point gave me a hint and I thought of trying it out and guess what it worked flawlessly it was eureka moment for me trust me.I did bit more study as I didn't new much about it and found it is quite performing (StackOverflow: here, here).
So the ultimate winner is "MemoryCache".
Stay tuned, I'll shortly post the link to a sample code, but its cake walk just use your favourite search engine and you should be good to go.
I didn't get any post talking about the retry mechanism so thought of putting it up. This is one of the problem to solve during SharePoint App Development.
Thanks for being so patience as it was quite a theoretical article.
If you have any comment, reach me at @AkhileshN