Generic Feature Receiver for Features that Deploy WebParts
Greg Galipeau wrote a thorough post on cleaning up your Web Part Gallery that is the basis for this post. To summarize, Greg shares a Feature Receiver he uses as a generic Feature Receiver for all his WebPart Features that simply removes the WebPart having the same name as the Feature’s DisplayName when the Feature is deactivated.
There are a couple of issues with this though:
- It assumes that the WebPart has the same name as the Feature
- It limits the Feature to deploying just a single WebPart
An alternative approach would be to inspect the Feature’s element definitions and extract the exact WebPart names that were deployed, thus resolving the two issues noted above.
Below is the alternative Feature Receiver (it extends the BaseFeatureReceiver I mentioned in my previous post):
public class WebPartFeatureReceiver : BaseFeatureReceiver<SPSite> { public override void FeatureDeactivating(SPSite site, SPFeatureReceiverProperties properties) { base.FeatureDeactivating(site, properties); var elements = properties.Definition.GetElementDefinitions(CultureInfo.CurrentCulture); var webparts = elements.Cast<SPElementDefinition>() .SelectMany(e => e.XmlDefinition.ChildNodes.Cast<XmlElement>() .Where(n => n.Name.Equals("File")) .Select(n => n.Attributes["Url"].Value) ) .ToList(); var rootWeb = site.RootWeb; var wpGallery = rootWeb.Lists["Web Part Gallery"]; var galleryItems = wpGallery.Items.Cast<SPListItem>() .Where(li => webparts.Contains(li.File.Name)) .ToList(); for (int i = galleryItems.Count - 1; i >= 0; i--) { var item = galleryItems[i]; item.Delete(); } } }
August 28th, 2009 at 2:36 pm
Nice work!
December 29th, 2009 at 12:10 am
What namespaces are required?
I can’t figure out what namespace is required to solve the error:
Error 1 ‘Microsoft.SharePoint.Administration.SPElementDefinitionCollection’ does not contain a definition for ‘Cast’ and no extension method ‘Cast’ accepting a first argument of type ‘Microsoft.SharePoint.Administration.SPElementDefinitionCollection’ could be found (are you missing a using directive or an assembly reference?)
December 29th, 2009 at 10:52 am
@Perry – Thanks for bringing this up. The ‘Cast’ method is an extension method located in the System.Linq.Enumerable class. You will need to include a using statement for the System.Linq namespace. Extension methods can be a little tricky to track down.
May 17th, 2010 at 9:03 am
Hi,
if you change
var wpGallery = rootWeb.Lists["Web Part Gallery"];
into
var wpGallery = rootWeb.GetList(“/_catalogs/wp”);
It will work in other languages
August 24th, 2011 at 5:39 am
Thanks for the solution.
I would recommend more unified way of loading web parts gallery (without string hardcoding):
var webPartsGallery = rootWeb.GetCatalog(SPListTemplateType.WebPartCatalog);
It works without problems for me.