Skip to main content

Cloud

CustomActionGroups are duplicated when defined in multiple features

I ran into some interesting behavior on a recent project related to CustomActionGroups. As you’re probably familiar, the SharePoint CustomAction element makes it pretty simple to extend (or suppress) SharePoint’s functionality. The CustomActionGroup element is related — and simply allows you to add your own application groups to contain custom functionality like this:

2008-09-29_222555

The XML for specifying this customization — in this case, adding some links to the "Site Settings" page — is pretty easy:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   3:  
   4:     <CustomActionGroup
   5:         Id="MyApp.CustomSettings"
   6:         Location="Microsoft.SharePoint.SiteSettings"
   7:         Title="MyApp Custom Settings" />
   8:  
   9:     <CustomAction
  10:         Id="MyApp.Configuration"
  11:         GroupId="MyApp.CustomSettings"
  12:         Location="Microsoft.SharePoint.SiteSettings"
  13:
     Sequence="1000"
  14:         Title="Application configuration">
  15:         <UrlAction Url="~Site/_layouts/MyApp/CustomSettings.aspx"/>
  16:     </CustomAction>
  17:  
  18: </Elements>

That’s great — but what if you have multiple features in your overall solution and want to have a different custom action from each feature that gets put into the same custom action group?

I ran into this scenario on a recent project, and I figured that if I declared the custom action group definition in each of the features but used the same "Id" attribute, that would ensure that the group would get created regardless of which features were activated and that if the group with that ID already existed, that SharePoint would put the custom action into the existing group.

Alas, I was wrong. If you have two features that both declare a custom action group with the same "Id" attribute and you activate both features, SharePoint will offer you something helpful like this:

2008-09-29_223003

Interesting, huh? So SharePoint adds the custom action group in twice, but they must both have the same "Id" attribute even internally, because the custom actions for both features end up in both instances. Both sets of links work fine — it’s just a visual nuisance to have the group replicated multiple times.

So what’s the solution?

It’s actually fairly simple: create a feature that defines the custom action group, then configure all of the other features that add custom actions to set their "GroupId" attributes to the same as the "Id" specified by the custom action group definition. In addition, it’s a good practice to add an activation dependency between the features to ensure that the custom action group definition exists.

In the end, here’s the XML. It’s the same as you see above, but broken into two different features. Here’s the XML in the feature that defines the custom action group:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   3:  
   4:     <CustomActionGroup
   5:         Id="MyApp.CustomSettings"
   6:         Location="Microsoft.SharePoint.SiteSettings"
   7:         Title="MyApp Custom Settings" />
   8:  
   9: </Elements>

And here’s the XML for one of the features that places a custom action into that group:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   3:  
   4:     <CustomAction
   5:         Id="MyApp.FeatureSettings"
   6:         GroupId="MyApp.CustomSettings"
   7:         Location="Microsoft.SharePoint.SiteSettings"
   8:         Sequence="1000"
   9:         Title="Modify feature settings">
  10:         <UrlAction Url="~Site/_layouts/MyApp/FeatureSettings.aspx"/>
  11:     </CustomAction>
  12:  
  13: </Elements>

Note the correlation between the value in the "Id" attribute in the group declaration and the "GroupId" in the custom action. In the end, here’s the result:

2008-09-29_225328

Much better. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Matthew Morse

More from this Author

Follow Us