Removing Provisioned Files from SharePoint During Feature Deactivation


As mentioned in this post, files provisioned into SharePoint using Feature Modules, do not get removed when the feature is deactivated. This may or may not be a problem to you, except that, my own experience has shown that, say, when upgrading features, existing files provisioned by a previous version of a feature, sometimes do not get overwritten, or new files in a new version of the feature sometimes get ignored if the file already exists. Meaning that you may not get the right files for your feature installed into SharePoint.

To work around this issue, what you can do is remove files programmatically when the feature is deactivated, and obviously for this you need a feature receiver.

The code to remove files from SharePoint is pretty generic since it invariably involves removing SPListItem files from a Document Library or Folder. Presented below is some code which looks at the Feature elements definitions and selects the Name of provisioned files (the URL attribute of a Module File element).

It then uses those file names to select the associated SPListItem‘s from the Site Collection Web Part Gallery in order to delete them.

	// get the top level site collection
	var spSite = properties.Feature.Parent as SPSite;
	if (spSite == null)
		throw new Exception(
			"Feature scope mismatch, Feature was not a Site scoped feature");

	// get the Feature elements definitions
	var fdElements = properties.Definition.GetElementDefinitions();
	// select the URL attribute values of File elements (Web Part files)
	var fdWebparts = fdElements.Cast<SPElementDefinition>()
			.SelectMany(el => el.XmlDefinition.ChildNodes.Cast<XmlElement>()
				.Where(fe => fe.Name.Equals("File"))
			.Select(fe => fe.Attributes["Url"].Value)
		).ToList();

	// grab the Web Part Gallery
	var wpGallery = spSite.RootWeb.Lists["Web Part Gallery"];

	// select SPListItems from the Web Part Gallery where the associated file name is one of
	// the previously selected Web Part file names
	var wpToDelete = wpGallery.Items.Cast<SPListItem>()
		.Where(wp => fdWebparts.Contains(wp.File.Name))
		.ToList();
	// and delete them from the document library (NOTE: the reverse processing order)
	for (var idx = wpToDelete.Count - 1; idx >= 0; idx--)
	{
		var item = wpToDelete[idx];
		item.Delete();
	}

Another option, depending on your needs, is much simpler.
Maintain a list of the files to be removed during deactivation as an array of name/value pairs, then some simple code to run over the list removing the files.

	// provisionedFiles is an array of name/value pairs, Name contains the folder name, Value contains the filename
	foreach (var provisionedFile in provisionedfiles)
	{
		// get the SPFolder
		var spfolder = spWeb.Folders[provisionedFile.Name];
		if (spfolder == null) continue;

		// format the URL of the file, find the file and delete it.
		var url = string.Format("{0}/{1}", provisionedFile.Name, provisionedFile.Value);
		var spFile = spfolder.Files[url];
		if (spFile != null)
		{
			spfolder.Files.Delete(url);
			spfolder.Update();
		}
		else
		{
			// file not found in sharepoint!!
		}
	}
About these ads

About Phil Harding

SharePoint Consultant, Developer, Father, Husband and Climber.

One Response to “Removing Provisioned Files from SharePoint During Feature Deactivation”

  1. Nice moves Phil. Love the digging it out of the elements.xml. Thanks for making the web a better place!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 598 other followers

%d bloggers like this: