Second Life of a Hungarian SharePoint Geek

April 30, 2018

Faking feature activation properties

Filed under: Features, Reflection, SP 2013, Tips & Tricks — Tags: , , , — Peter Holpar @ 21:19

Assume you have a feature receiver in your SharePoint project. You would like to perform multiple actions if the feature is activated, so you organize your code according to the actions into static methods of a helpers class, like shown in the code snippet below:

  1. [Guid("8cb098ae-2017-4fff-8a53-b315abb85d79")]
  2. public class YourFeatureReceiver : SPFeatureReceiver
  3. {
  4.     public override void FeatureActivated(SPFeatureReceiverProperties properties)
  5.     {
  6.         SomeHelperClass.DoSomethingOnTheSite(properties);
  7.         SomeHelperClass.DoSomethingOtherOnTheSite(properties);
  8.         SomeHelperClass.AndFinallyDoThat(properties);
  9.     }
  10. }

Note: In this case, it is a site level feature, and we handle the FeatureActivated event, but you can apply the same technique for other kinds of feature receivers and events as well.

A helper method has the following signature, and contains code like this one:

  1. public static void DoSomethingOnTheSite(SPFeatureReceiverProperties properties)
  2. {
  3.     SPSite site = properties.Feature.Parent as SPSite;
  4.     if (site != null)
  5.     {
  6.         // do something here
  7.     }
  8. }

You would like to test the functionality of your method one-by-one from a console application, without actually having to deploy your SharePoint solution an activate your feature each time again (of course, you need at least an initial deployment of the whole solution). In my case, the helper class is included in a separate assembly, but even if it is the assembly of your SharePoint project, you should only deploy the new version of the assembly into the Global Assembly Cache (GAC).

As you can see in the method above, we use the Feature property of the SPFeatureReceiverProperties class we received in the properties parameter. Of course, the Feature property is read-only, so we need some tricks, to be able to pass the SPFeatureReceiverProperties parameter populated with the correct SPFeature in its Feature property to the method. We create first a new instance of the SPFeatureReceiverProperties class, than query the site for the feature based on its ID (se my important notice about this ID after the code block!). We can inject this SPFeature instance into our formerly crated SPFeatureReceiverProperties instance using Reflection, via the internal SetFeature method of the SPFeatureReceiverProperties class. Finally, we can invoke our helper method with the already-populated properties variable.

  1. using (SPSite site = new SPSite(yourSiteUrl))
  2. {
  3.     var properties = new SPFeatureReceiverProperties();
  4.  
  5.     var yourFeatureId = new Guid("51bf2a39-b527-46cf-abd6-39aaf1dcd19b");
  6.  
  7.     var feature = site.Features.FirstOrDefault(f => f.DefinitionId == yourFeatureId);
  8.     if (feature != null)
  9.     {
  10.         MethodInfo mi_setFeature = typeof(SPFeatureReceiverProperties).GetMethod("SetFeature",
  11.             BindingFlags.NonPublic | BindingFlags.Instance);
  12.  
  13.         if (mi_setFeature != null)
  14.         {
  15.             mi_setFeature.Invoke(properties, new object[] { feature });
  16.             SomeHelperClass.DoSomethingOnTheSite(properties);
  17.         }
  18.     }
  19. }

Note: It is important to notice, that the Guid we used in the feature-lookup above, comparing it to the DefinitionId property, is not the same, as the Guid we saw earlier in the feature receiver code snippet. The latter one is used only by Visual Studio during the deployment process to find up the correct ReceiverClass for the event receiver. The Guid we need, the ID of the feature is available on the Manifest tab of the feature as illustrated below:

image

Applying this technique made our development and testing process a lot faster.

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: