Over my years in SharePoint development I have had the following issue occur.a couple of times.
Actually back in July 2010, I posted a blog entry which solved a problem with the Manage Content and Structure page which was related to duplicate lists in a site.
- I create a custom List with a customised List Definition which uses a schema.xml to define the List Template
- I create a Feature which uses the customised List Definition to create a new List Template with the <ListTemplate> feature element.
- I configure the feature to create an Instance of the list using the <ListInstance> feature Xml element,
- Activate the feature in a SharePoint Web, click Site Actions->View All Site Content.
- Two instances of the list appear in the View All Content page, both reference the same SharePoint list.
- Figure below shows an example of two duplicate lists in the web.
I have then always wondered what causes this?
What is interesting is that one link points to one view and the other link points to a different view, this hint was the lead to help solve the issue.
I started the investigation by digging into the SharePoint databases now quick warning, “you should not read or edit the database, doing so will leave your SharePoint installation unsupported by Microsoft!”
However, I was very careful and did not make any changes to the database.
It was one of the tables that lead me to working out why I was having these duplicate links. This table was the BuildDependencies table. I performed a
SELECT TOP 1000 [SiteId]
Where [DirName] LIKE ‘sites/sitename%’
Looking through the results I could see that the list had two views one called ‘ByFeatures.asppx and the other ‘AllItems.aspx’
This was correct my List Schema had defined these two views and then it dawned on me, what if SharePoint is looking at the schema.xml to work out which list page to display in the View All Content page.
So I went into my schema.xml and low and behold there was an attribute on the <View> element called DefaultView. Now both the AllItems.aspx and ByFeatures.aspx had this set to TRUE.
So to fix this I followed this process:-
- Updated the schema.xml <View/> element for the AllItems.aspx view
- Modified the DefaultView attribute and set it to FALSE
- Redeployed the solution
- Perform an IISRESET
- Deactivate the Feature
- Delete the list
- Activate the Feature to create the list
Now I only see one instance of the list in the View All Content page.
However, there is a problem with this approach and that is you lose the data in the list!
To Fix Existing Lists with No data loss
So we need a way to fix the lists that have already been created, seeing as the existing lists are not fixed by the schema changes then these properties must have been copied into the content database.
So to fix existing lists do the following:-
- Browse to the list and open up the List Settings page using the Ribbon
- Create a new View call it what you want, make sure you set it to default
- This will reset the Default View attribute on the other views and make the new view the default view.
- Modify the view that should really be the default view and tick the make default view checkbox. (This doesnt appear if you have multiple views with the default view set).
- Update the view
- Delete any views that are not needed
You should now see only one list instance in the View All Site Content page!
Although a SharePoint developer should try their best to use the tools that SharePoint provides inevitably the client will ask for something that needs some custom code! Over the last few years the customer has demanded that the code be fast, reliable and scalable.
When this happens one of the first things you start to think about is performance. Hand in hand with performance is caching so that you can reduce the number of expensive operations.
However, when you cache data you get into scenarios where users make a change but they are not reflected immediately. The users then start complaining because the cache has become stale.
There are a few solutions:-
- Restart IIS / OWS Timer Service to flush the cache (not practical)
- Decrease the lifetime of the cache object (increase the number of expensive ops)
- Use Cache Dependencies to flush the cache
The last option is the best as it supports options when data is being shared across multiple application domains however it doesn’t help when you have a number of servers in your SharePoint farm.
This is why I built the framework. The framework allows you to control the caching of objects across the SharePoint Farm.
The way it works is pretty straightforward and it comes with a small API to allow you to use it in your solutions.
The framework is made of a few components:-
- Cache Configuration SharePoint List to manage the configuration
- Cache Configuration Refresh Timer Job to perform the cache update
- Cache Configuration Manager – API to manage the Cache Refresh Configuration
- Cache Refresh PowerShell Cmdlets to administrate the framework
- Base Classes for Managing Configuration Objects
The way that the framework work is that an object is cached with a dependency to a particular file on the server’s file system. This uses .NET built in CacheDependencies which run a file watcher against the file. When the file being watched is modified a callback occurs and the cache item is removed from the HTTPRuntime.Cache.
The Cache Refresh Framework provides a method using SharePoint Timer Jobs to run a process which modifies these files across all SharePoint Servers in a farm. This flushes the object from the Cache on each of the servers in the farm so that next time they load the object it is loaded from the Data Access Layer / Storage Mechanism rather than the Cache.
The framework supports multiple cache profiles so that you can group objects to be refreshed together or target them differently.
The following section explains some usages and the process in more detail.
The framework can be used to allow caching of objects such as:-
- Configuration items
- Navigation items
- XML elements
- Plain Old C# Objects (POCO)
- Data Transfer objects (DTOs)
A common example is:-
- A user of the system makes a change to the configuration.
- The SharePoint Application calls into the Cache Refresh Framework tell it to refresh a particular Cache Configuration
- The Cache Refresh Framework gets the Cache Configuration and runs the timer job for that configuration on all servers in the SharePoint farm using the SharePoint Farm Timer Service.
- Each server runs the actual job which modifies a file
- The Cache Dependency picks up the change to the file and flushes the cache
- The next time the application gets that object it get its from the data access layer rather than the cache.
Deployment, Configuration, How To Examples
The framework has been uploaded to Codeplex as the SharePoint Cache Refresh Framework Project and there are a number of guides which cover:-
- How-to Examples
- Code Documentation
These can be found in the Documentation Section
Currently the framework is an alpha release, so there might be some issues with it, so please don’t try it on your production environment without plenty of testing. There are some known issues and I will look to improve the framework and fix those issues as they are found. However, I am excited about getting the framework out there and getting feedback on it.
If you have any ideas for additional functionality then please add a Discussion item.
Finally, please let me know if you find it useful and how you have used it!