How to Write SharePoint Custom Actions

You create a SharePoint action to add custom buttons to the ribbon or settings pages. Actions can be created in Visual Studio and consist of a single Elements file. Multiple actions can be deployed with just one file. In typical SharePoint style, a web-level feature is used to install the action(s). 

Important AttributesWrite_SharePoint_Custom_Actions_by_Kayla_Funke_2.png

The appearance and functionality of your action is defined in Elements.xml using the CustomAction node as a base. This node has several common attributes that developers should be familiar with:

Location

There are a variety of places developers can insert custom buttons and links. There are page ribbons, list ribbons, item ribbons, item context menus, list settings, site settings, etc. Specify this broad area with the Location attribute.

Group

Within each ribbon or page, developers must also decide which control group they want their actions to reside in. They may choose an existing control group, or create a custom one. SharePoint provides a useful reference of all predefined locations and groups.

Sequence

Sequence defines where the action will appear within a group. The lower the number, the closer to the front of the group the control will appear. Zero represents the first position. A good practice is to use numbers greater than or equal to 2000 to prevent custom actions from interfering with native controls. The best way to determine the correct sequence number is to experiment.

Registration Type and ID

If you wish to limit your action to a specific list or set of lists, you will need to include both RegistrationType and RegistrationId (one does not work without the other). Commonly used RegistrationTypes are List and ContentType.

For lists, RegistrationId should be equal to the base template identifier of the list (ex. 100 for GenericList, 101 for DocumentLibrary, 106 for Events, etc). This means you cannot use the List RegistrationType to target specific list instances, but rather categories of lists.

For content types, RegistrationId should be equal to a content type identifier, which contains information about each of its parent content types and follows this format:

0x010018F1A02DF723124EB9E5F32E2FBA86C7

Target Specific List or Library

If a developer must target a specific list, they should create a custom content type for that list alone, and point the action at that content type.

Target All Lists and Libraries

Developers commonly need to target all lists and libraries, no matter their template ID or content types. This is easy due to the hereditary nature of content type identifiers. Simply set RegistrationType to ContentType and RegistrationId to 0x. This is the system content type from which all lists and libraries inherit.

Rights

Set this to a SharePoint base permission in order to control who may see your custom action and who may not. For example, if a custom action provides additional control over a list, you may want to set Rights to ManageLists so that only admins with the ability to create and delete lists may see it.

Basic Setup

Setup custom action in How to Write SharePoint Custom actions blog post by Kayla Funke at Easy DynamicsThe initial setup for a custom action is simple:

  1. Create an empty SharePoint 2010 or 2013 farm project.
  2. Add an Empty Element to the project. Visual Studio will automatically add a web-level feature for you.
  3. Add a CustomAction node to your Elements file and flesh it out.

List Settings Action

To deploy an extra link to a list settings page, use the Microsoft.SharePoint.ListEdit Location and choose from Groups like GeneralSettings and Permissions.

Most of the time, you will want the link to direct to a custom application page. Use the UrlAction node to describe this behavior. You may include JavaScript in the Url attribute of this node. SharePoint will also automatically fill in special tokens like {ListId} to help your custom page identify the context of the request. If needed, leverage _spPageContextInfo, a useful SP JS global variable, to include current SPWeb information.

<CustomAction Id="CustomActionDemo.ListSettingsAction"
    Title="My Custom Settings"
    Location="Microsoft.SharePoint.ListEdit"
    GroupId="GeneralSettings"
    Rights="ManagePermissions">
    <UrlAction Url="javascript:window.open(_spPageContextInfo.webServerRelativeUrl + '/_layouts/Custom_Settings/ListSettings.aspx?ListId={ListId}');" />
</CustomAction>

list settings in How to Write SharePoint Custom actions blog post by Kayla Funke at Easy Dynamics

Site Settings Action

To deploy an extra link to the site settings page, use the above example as a base. Change Location to Microsoft.SharePoint.SiteSettings and choose from several groups like SiteAdministration and SiteCollectionAdmin.

List Item and Document Actions

Adding a custom button to the ribbon for list items and documents is more complicated. Multiple actions are usually required in order to display the new button everywhere it may be needed—the display form, the edit form,{{cta(‘d173b5b6-18d9-4d5d-9383-d06f0cfdfa78′,’justifyright’)}} the create form, the list view, etc.

A different format is needed in order to add a button to the ribbon of any of the above pages. Start with an action for the CommandUI.Ribbon Location. Add a CommandUIDefinition node for each form you wish the button to appear on, and a corresponding CommandUIHandler to describe what should happen when the button is clicked.

Below is an example of adding a button (icon included) to both the list view and the display form of all generic lists:

<CustomAction 
    Id="CustomActionDemo.RibbonAction"
    Location="CommandUI.Ribbon"
    RegistrationType="List"    
    RegistrationId="100">
    <CommandUIExtension>
        <CommandUIDefinitions>

            <CommandUIDefinition 
                Location="Ribbon.ListItem.Manage.Controls._children">
                <Button Id="CustomActionDemo.ListViewAction"
                    Command="Command.CustomActionDemo.ListViewAction"
                    LabelText="My Custom Settings"
                    Sequence="1000"
                    Description="Edit custom settings for this list item."
                    Image32by32="_layouts/Images/Custom_Settings/icon_32x32.png"
                    Image16by16="_layouts/Images/Custom_Settings/icon_16x16.png"
                    Alt="Custom Settings"
                    TemplateAlias="o1" />
            </CommandUIDefinition>
            
            <CommandUIDefinition 
                Location="Ribbon.ListForm.Display.Manage.Controls._children">
                <Button Id="CustomActionDemo.DisplayFormAction"
                    Command="Command.CustomActionDemo.DisplayFormAction"
                    LabelText="My Custom Settings"
                    Sequence="1000"
                    Description="Edit custom settings for this list item."
                    Image32by32="_layouts/Images/Custom_Settings/icon_32x32.png"
                    Image16by16="_layouts/Images/Custom_Settings/icon_16x16.png"
                    Alt="Custom Settings" 
                    TemplateAlias="o1" />
            </CommandUIDefinition>

        </CommandUIDefinitions>
        <CommandUIHandlers>

            <CommandUIHandler
                Command="Command.CustomActionDemo.ListViewAction"
                CommandAction="javascript:window.open(_spPageContextInfo.webServerRelativeUrl + '/_layouts/Custom_Settings/ListSettings.aspx?ListId={ListId}&amp;ItemId={SelectedItemId}');"
                EnabledScript="javascript:SP.ListOperation.Selection.getSelectedItems().length == 1" />
        
            <CommandUIHandler
                Command="Command.CustomActionDemo.DisplayFormAction"
                CommandAction="javascript:window.open(_spPageContextInfo.webServerRelativeUrl + '/_layouts/Custom_Settings/ListSettings.aspx?ListId={ListId}&amp;ItemId={ItemId}');" /> 
 
        </CommandUIHandlers>
    </CommandUIExtension>
</CustomAction>

The CommandUIHandler for ListViewAction needs to do a little extra work. The button should only be enabled if a single list item is selected. Lucky for us, we can use JavaScript to determine this by providing the EnabledScript attribute with the following condition:

SP.ListOperation.Selection.getSelectedItems().length == 1

This is what ListViewAction will look like if you install it:

list view action installation in How to Write SharePoint Custom actions blog post by Kayla Funke at Easy Dynamics

And this is what DisplayFormAction will look like:

display form action installation in How to Write SharePoint Custom actions blog post by Kayla Funke at Easy Dynamics

Documents

Note that the ListViewAction will only work for items in a list due to the Location it uses. If you wish to target documents in a library instead, substitute the location of Ribbon.ListItem.Manage.Controls._children with Ribbon.Documents.Manage.Controls._children and update RegistrationId. The definition will otherwise remain the same. DisplayFormAction will work for both documents and items.

Context Menu Action

A context menu appears when you click on the down arrow beside the Title or equivalent column of a list or library. You can add custom actions to this menu as well. Below is an example of a context menu action applied to all lists and libraries.

<CustomAction
    Id="CustomActionDemo.ContextMenuAction"
    Title="My Custom Settings"
    Location="EditControlBlock"
    RegistrationType="ContentType"
    RegistrationId="0x"
    Sequence="2000"
    Description="Edit Custom Settings for this list item."
    ImageUrl="_layouts/Images/Custom_Settings/icon_16x16.png">
    <UrlAction Url="javascript:window.open(_spPageContextInfo.webServerRelativeUrl + '/_layouts/Custom_Settings/ListSettings.aspx?ListId={ListId}&amp;ItemId={ItemId}');" />
</CustomAction>

context menu in How to Write SharePoint Custom actions blog post by Kayla Funke at Easy Dynamics


What other tips on writing custom SharePoint actions have been helpful in your daily work? Share your wisdom with us in a comment below!

Found this blog post useful? Make yourself comfortable and check out our blog home page to explore other technologies we use on a daily basis and the fixes we’ve solved in our day to day work. To make your life easier, subscribe to our blog to get instant updates sent straight to your inbox:

{{cta(‘33985992-7ced-4ebd-b7c8-4fcb88ae3da4′,’justifycenter’)}}

Author

Leave a Comment