SharePoint SPList Cache Dependency

When working customized solutions i SharePoint caching custom objects may be a good idea. The standard ASP.net cahce i commonly used with a expiry time specified in seconds or minutes depending on how “fresh” the data needs to be. Objects cached in a customized SharePoint solution are often representations of content within SharePoint lists. In that case a cache dependency against the SharePoint resource might be a good idea.

I´m going to show how to create a custom cache dependency class that adds dependency to a list.

The custom implementation in SPListCacheDependency is set up to check a list for changes every ten seconds. The class can be modified to monitor other SharePoint resources as well.

public class SPListCacheDependency : CacheDependency
{
	private readonly SPListCacheDependencyEventArgs _eventArgs;
	private readonly Timer _timer;
	private readonly DateTime _lastModified;
	private readonly int _itemCount;
	private readonly string _uniqueId;

	public SPListCacheDependency(SPList list)
	{
		_lastModified = list.LastItemModifiedDate;
		if (list.LastItemDeletedDate > _lastModified)
		{
			_lastModified = list.LastItemDeletedDate;
		}

		_itemCount = list.ItemCount;
		_uniqueId = list.ID.ToString() + list.ParentWeb.ID + list.ParentWeb.Site.ID;
		_eventArgs = new SPListCacheDependencyEventArgs(list.ParentWeb.Site.ID, list.ParentWeb.ID, list.ID);
		_timer = new Timer(10000) { AutoReset = true }; // check every ten second
		_timer.Elapsed += MonitorChanges;
		_timer.Start();
	}

	public override string GetUniqueID()
	{
		return _uniqueId;
	}

	public bool HasObjectChanged(object source)
	{
		SPList list = (SPList)source;
		DateTime modified = list.LastItemModifiedDate;

		if (list.LastItemDeletedDate > modified)
			modified = list.LastItemDeletedDate;

		return _lastModified != modified || _itemCount != list.ItemCount;
	}

	private void MonitorChanges(object sender, ElapsedEventArgs e)
	{
		try
		{
			using (SPSite site = new SPSite(_eventArgs.SiteId))
			{
				using (SPWeb web = site.OpenWeb(_eventArgs.WebId))
				{
					SPList list = web.Lists[_eventArgs.ListId];
					ObjectChanged(list);
				}
			}
		}
		catch (ArgumentException)
		{
			//Object has been deleted.
			ObjectChanged(null);
		}
	}

	/// <summary>
	/// Raise event and stop timer if object has been updated
	/// </summary>
	/// <param name="item"></param>
	private void ObjectChanged(object item)
	{
		if (!HasObjectChanged(item) && item != null) return;

		_timer.Stop();
		NotifyDependencyChanged(this, _eventArgs);
	}
}

/// <summary>
/// Information holding object for a SharePoint List cache dependency object.
/// </summary>
internal class SPListCacheDependencyEventArgs : EventArgs
{
	public SPListCacheDependencyEventArgs(Guid siteId, Guid webId, Guid listId)
	{
		SiteId = siteId;
		WebId = webId;
		ListId = listId;
	}

	public Guid SiteId { get; private set; }
	public Guid WebId { get; private set; }
	public Guid ListId { get; private set; }
}

The usage of the class SPListCacheDependency is simply:


HttpContext.Current.Cache.Add("MyCacheKey",
myObjectsToCache,
new SPListCacheDependency(MySPList),
System.Web.Caching.Cache.NoAbsoluteExpiration,
System.Web.Caching.Cache.NoSlidingExpiration,
CacheItemPriority.Normal,
null);

Custom JavaScript events

February 16, 2012 Leave a comment

Modern SharePoint development often means incorporating WCF web services in connection with ajax calls from visual web parts. In this manner, we can avoid postbacks when a user interacts with the web part or when the web part needs updating. In comparison, regular web parts require postbacks as a result of user interaction. Although it is possible to do ajax calls from regular web parts, the declarative approach with visual web parts lead to more maintainable solutions.

Sometimes web parts affect each other, e.g. when you have a filter web part that filters a list view web part. This is traditionally solved by using connected web parts. In many situations this might be the most straight-forward approach, and you can also avoid complete page updates by using the UpdatePanel control. However, another solution for the flickering page problem is Custom JavaScript events.

Javascript code is essentially triggered by events, such as the onload and the onclick events. However, if you have a filter web part that filters another web part and you don’t want ugly dependent JavaScript code inside the filter web part’s onclick event handler, then a custom JavaScript event is what you need. This is a loosely coupled approach where the filter web part doesn’t need to know which other listeners or subscriber web parts there are on the page.

Let’s demonstrate this with an example. We have the following scenario: A process tree control (visual web part) interacts with a process map control (visual web part). When a user selects a process node in the process tree control, then the process map will highlight the selected process box, and vice versa. For more details, check out the example here.

A similar solution maybe to use jQuery events, which actually use custom JavaScript events.

References: Custom events in JavaScript by Nicholas C. Zakas

Hello world!

November 28, 2011 1 comment

Welcome to WordPress.com. After you read this, you should delete and write your own post, with a new title above. Or hit Add New on the left (of the admin dashboard) to start a fresh post.

Here are some suggestions for your first post.

  1. You can find new ideas for what to blog about by reading the Daily Post.
  2. Add PressThis to your browser. It creates a new blog post for you about any interesting  page you read on the web.
  3. Make some changes to this page, and then hit preview on the right. You can always preview any post or edit it before you share it to the world.
Categories: Uncategorized