Tuesday, May 22, 2012

Site Pages in Non-Team Sites

The problem:

I am creating a site from my site collection feature receiver; the site is not a team site, but it does need to have the Site Pages library. You might recall that on every team site this library is automatically provisioned, because of  the WikiPageHomePage feature; however, the problem is that this feature cannot be activated in non-team sites.

The solution:

Since I have to activate the feature in code, the best way to do it is to obtain the reference to the site that is being created and then call the EnsureSitePagesLibrary():

SPWeb web = ...
SPList list = web.Lists.EnsureSitePagesLibrary();

Note that, in a similar fashion, you can provision a Site Assets library in a non-team site - just call EnsureSiteAssetsLibrary(), rather than EnsureSitePagesLibrary().

Wednesday, May 9, 2012

Caching Web Part Content

The problem:

Here is a common scenario. You have a web part whose contents include a gridview, which is populated by going through all (or many) subsites and gathering the information from each of these sites. The gridview has to allow sorting and possibly even filtering.

The problem, though, is that sorting and filtering typically cause postback, which means you need to perform the expensive operation of loading the data again. If the data happens to be static (or relatively static), you wind up loading the same data over and over again, which results in performance deterioration.

The solution:

The solution depends on whether the data displayed the gridview is the same for every user.

a) If it is the same, then it will be worthwhile to use the Cache object and add the datatable (or any other data source object) to the cache if it is not already there. This will speed up the loading time for every user, since the cache will be populated only once. A couple of gotchas, though:

1) Make sure you place a lock around the code that accesses cache. Otherwise, if it takes 15 seconds to load the data table and many users are trying to access this page at the same time, then all of these users will be simultaneously trying to update the same cache object - and this would result in performance problems.

2) If the data occasionally changes, it would be wise to implement cache dependency, so that the cache is invalidated whenever the data changes.

b) If it is not the same, then use Session instead of Cache. But, make sure the session state is enabled. Another gotcha is that there is no expiration of the Session object, nor there is anything equivalent to cache dependency for Session objects - so you'll need to find some other way to clear the session object once the underlying data table changes.

Tuesday, May 8, 2012

Provisioning Site Pages

Today I'd like to talk about provisioning pages in a feature. Sometimes your customer wants to add some content to the pages you provision, and/or to have some web parts on them.. If that's the case, application pages will not do - they live on the file system (more specifically, LAYOUTS on the hive, or some subfolder of LAYOUTS), and you cannot add web parts to them.

Provisioning site pages using Visual Studio 2010 is a little harder than provisioning application pages - after all, there is no such an item template as "Site Page" or "Web Part Page." So, you will need to use a workaround.

First of all, you need to remember that when you provision files, you do so via modules. Luckily, there is such an item template. When you create a module, an Elements.xml file and a Sample.txt files are added to your Visual Studio 2010 project.

Rename Sample.txt to YourSitePage.aspx (or whatever name you'd like to use for your page), and add the following:


Note that in the PlaceHolderMain, I am creating a new web part zone, called MainWebPartZone (feel free to rename it if you don't like this name.) This is where the web part will live on this page.

Also add a class to your module and name it YourSitePage.aspx.cs.  This will be the code-behind class for your page.

The next step is configuring the module. If you want your user to treat your page as a library item, you need to provision it as ghostable in library. In the CDATA section, insert the full contents of the .webpart file (except the processing instruction!) In my example, the new page is provisioned in the Pages library.