Monthly Archive for April, 2009

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:

  1. It assumes that the WebPart has the same name as the Feature
  2. 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();
            }
        }
    }

(SPWeb)properties.Feature.Parent no more … a handy Feature Receiver Base Class

If you are writing SharePoint feature receivers often, you will find there are several lines of code common to just about every feature receiver:

  1. A cast of properties.Feature.Parent to the appropriate scope (either SPWeb, SPSite, SPWebApplication, or SPFarm)
  2. Empty implementations of FeatureInstalled and FeatureUninstalling

Provided below is an abstract generic class that now serves as the base class for every feature receiver I write. It eliminates the redundant code by performing the cast for you based on the classes generic type parameter and also goes ahead and implements all the abstract methods, making it so that you to only need to override the actual methods you plan to handle. Your extending feature receiver now will look like the following:

    public class MyFeatureReceiver : BaseFeatureReceiver<SPWeb>
    {
        public override void FeatureDeactivating(SPWeb scope, SPFeatureReceiverProperties properties)
        {
            // Pointless, but what the heck
            base.FeatureDeactivating(scope, properties);
 
            // Now do something with your scope object, in this case an SPWeb
            ...
        }
    }

And now, the code for the BaseFeatureReceiver:

    /// <summary>
    /// Base class that makes the feature scope available as an argument to the
    /// FeatureActivated and FeatureDeactivating methods
    /// </summary>
    /// <typeparam name="T">
    /// T is the class type of the scope of the feature (SPFarm, SPWebApplication, SPSite, or SPWeb)
    /// </typeparam>
    public abstract class BaseFeatureReceiver<T> : SPFeatureReceiver
    {
        public sealed override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            FeatureActivated((T)properties.Feature.Parent, properties);
        }
 
        public virtual void FeatureActivated(T scope, SPFeatureReceiverProperties properties) { }
 
        public sealed override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            FeatureDeactivating((T)properties.Feature.Parent, properties);
        }
 
        public virtual void FeatureDeactivating(T scope, SPFeatureReceiverProperties properties) { }
 
        public override void FeatureInstalled(SPFeatureReceiverProperties properties) { }
        public override void FeatureUninstalling(SPFeatureReceiverProperties properties) { }
    }

Hope you find this helpful.

nHibernate in the Enterprise

I just recently received this response regarding the use of nHibernate within the division of the company I am working with:

… [nHibernate] has alot of promise I think but [coorporate] doesn’t consider it “stable” yet …

Are you kidding me? Where do these guys get their information? I guess the Microsoft Entity Framework is stable enough though.

Lets see, nHibernate is a port of the Java Hibernate Framework which was first released on November 30, 2001 (making it almost 8 years old). The major 1.2.1 version of nHibernate was released in November 2007, improving on the already stable port of the the Hibernate framework, adapting .Net 2.0 language features.

I began using the Hibernate framework in the Fall of 2005 being introduced to it by my colleague Winston Fassett. I switched over to .Net development in the Fall of 2006, and have been using nHibernate from the start.

Having used nHibernate since before the 1.2.1 release, I can safely vouch for its stability and performance … visit http://racenation.com for an example of my most recent nHibernate project.

I can’t say that some of the surrounding projects like Linq to nHibernate, although very cool, can be considered stable, but how long does a framework need to be around and used to be considered stable?