SharePoint Delegate Controls
Posted by PANVEGA on October 12, 2008
DelegateControl that you find in a lot of places in the master pages (especially the default.master). Essentially the Delegate Control provides an alternative to adding user controls and server controls to a .aspx page in the normal way.
What exactly is a Delegate Control?
You could see the DelegateControl as a mini SmartPart, a generic control that is able to render a user control you want to appear in your pages. This is new to WSS v3, and provides an excellent method of customization without touching the default SharePoint pages. Using delegate controls, we can easily customize or replace many of the default SharePoint pages and user controls, including those that are found in many disparate locations (such as the search bar). Delegate controls can either be web controls, as specified in the preceding example, or user controls. If you’re specifying a user control, use a Url attribute in the control instead of the ControlClass and ControlAssembly attributes.
<Control Id="SmallSearchInputBox" Sequence="50" ControlClass= "Microsoft.SharePoint.Portal.WebControls.SearchBoxEx" ControlAssembly= "Microsoft.SharePoint.Portal, Version=126.96.36.199, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
Many of the SharePoint pages have a reference for a DelegateControl, as follows:
Well, suppose you have this a custom image in 1000 pages on your site rendered through the DelegateControl technique. What if you want to make available a new user control, showing other content, maybe other functionality? Pretty easy. Create a new ASCX and drop it also in the ControlTemplates folder.
But think of it, SharePoint is using the same technique for showing the search box on the pages. You can find the definition of this in the default.master. You might have a lot of these in production. How can you quickly replace this search box with your own custom search box.
Controls are identified based on the functionality that is provided by the control. You can register controls for these functionalities through Feature elements. You specify which sort of control to use, a sequence number, and a URL to either a control template or an assembly, as shown in the following code examples:
|<?xml version=”1.0″ encoding=”utf-8″ ?> <Elements xmlns=”http://schemas.microsoft.com/sharepoint/”> <Control Id=”SmallSearchInputBox” Sequence=”100″ Url=”/templates/mysearchcontrol.ascx”/> </Elements>|
The following control replaces the previous control because it specifies a lower sequence number.
|<?xml version=”1.0″ encoding=”utf-8″ ?> <Elements xmlns=”http://schemas.microsoft.com/sharepoint/”> <Control Id=”SmallSearchInputBox” Sequence=”50″ ControlClass=”MySearchControl” ControlAssembly=”MyAssembly”/> </Elements>|
The DelegateControl is embedded inside Windows SharePoint Services pages and acts based on this information, as follows:
At run time, this control accepts the union of control elements declared at the server farm, Web application, site collection, and Web site levels. The control that has the lowest sequence number is added to the control tree by means of the DelegateControl. In the case of a sequence tie, the order of controls is arbitrary.
The sequence number allows a control to override another control – the lowest sequence number will always win. Take for example the following diagram….
In this case 3 features have been activated – Feature A, Feature B and Feature C. All are placing controls into MyControl. Because Feature B has the lowest sequence number, it wil be rendered onto the page at runtime, irrespective of when it was activated. If FEATURE B is deactivated, then FEATURE C will win.
The out-of-the-box default.master defines these delegate controls for you to override:
Of these, only the AdditionalPageHead is set to allow multiple controls. Notice that PublishingConsole is defined, which is true even if MOSS isn’t installed.
How to create a Delegate Control Feature Example:
<Feature xmlns=”http://schemas.microsoft.com/sharepoint/” Id=”XXXXXXXXXXXXXXXXXXXXXX”
<Control Id=”AdditionalPageHead” Sequence=”95″ ControlSrc=”~/_controltemplates/MyUserControl.ascx”/>
<SharePoint:DelegateControl runat=”server” ControlId=”AdditionalPageHead” AllowMultipleControls=”true”/>
It is important using the same ControlID like in your master page, here AdditionalPageHead.
originalWorkflowCommand = AddWorkflowsMenuItem; // that is the original name
AddWorkflowsMenuItem = AddWorkflowsMenuItemForListManager;
function AddWorkflowsMenuItemForListManager(m, ctx)
if(HasRights(0x0, 0x800)) // 0x800 = ManageLists
originalWorkflowCommand(m, ctx); // call original menu
Other good example:
<SharePoint:DelegateControl runat=”server” id=”DelctlProfileRedirection” ControlId=”ProfileRedirection” Scope=”Farm” />
This particular example is a reference from the userdisp.aspx page (located in c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\LAYOUTS), which controls the display of the user profile details (available via Welcome > My Settings). Other files with references to Delegate Controls in the LAYOUTS directory include:
- AddNavigationLinkDialog.aspx: ControlId=”AddNavigationLinkDialogPanel1″ Scope=”Site”
- AddNavigationLinkDialog.aspx: ControlId=”AddNavigationLinkDialogPanel2″ Scope=”Web”
- AreaNavigationSettings.aspx: ControlId=”NavigationSettingsPanel1″ Scope=”Site”
- AreaNavigationSettings.aspx: ControlId=”NavigationSettingsPanel2″ Scope=”Web”
- BackLinks.aspx: ControlId=”SmallSearchInputBox”
- ExcelProfilePage.aspx: ControlId=”VariationsFlagControl”
- ExcelProfilePage.aspx: ControlId=”GlobalSiteLink1″ Scope=”Farm”
- ExcelProfilePage.aspx: ControlId=”GlobalSiteLink2″ Scope=”Farm”
- groups.aspx: ControlId=”QuickLaunchDataSource”
- listcontentsources.aspx: ControlId=”QuickLaunchDataSource”
- listservernamemappings.aspx: ControlId=”QuickLaunchDataSource”
- logsummary.aspx: ControlId=”QuickLaunchDataSource”
- logviewer.aspx: ControlId=”QuickLaunchDataSource”
- managecrawlrules.aspx: ControlId=”QuickLaunchDataSource”
- managefiletypes.aspx: ControlId=”QuickLaunchDataSource”
- manageprivacypolicy.aspx: ControlId=”QuickLaunchDataSource”
- manageservicepermissions.aspx: ControlId=”QuickLaunchDataSource”
- mycontactlinks.aspx: ControlId=”ColleaguesLink1″ Scope=”Farm”
- newsbweb.aspx: ControlId=”CreateSitePanel1″ Scope=”Site”
- people.aspx: ControlId=”QuickLaunchDataSource”
- personalsites.aspx: ControlId=”QuickLaunchDataSource”
- profmain.aspx: ControlId=”QuickLaunchDataSource”
- quicklinks.aspx: ControlId=”AddColleaguesLink1″ Scope=”Farm”
- regionalsetng.aspx: ControlId=”RegionalSettingsExtensions”
- schema.aspx: ControlId=”QuickLaunchDataSource”
- scsignup.aspx: ControlId=”CreateSiteCollectionPanel1″ Scope=”Farm” />
- searchsspsettings.aspx: ControlId=”QuickLaunchDataSource”
- SiteManager.aspx: ControlId=”GlobalSiteLink1″ Scope=”Farm”
- SiteManager.aspx: ControlId=”GlobalSiteLink2″ Scope=”Farm”
- user.aspx: ControlId=”QuickLaunchDataSource”
- userdisp.aspx: ControlId=”ProfileRedirection” Scope=”Farm”
- VersionDiff.aspx: ControlId=”SmallSearchInputBox”
- viewlsts.aspx: ControlId=”QuickLaunchDataSource”
- viewscopes.aspx: ControlId=”QuickLaunchDataSource”
- XLViewer.aspx: ControlId=”GlobalSiteLink1″ Scope=”Farm”
- XLViewer.aspx: ControlId=”GlobalSiteLink2″ Scope=”Farm”
However, lets get back to that userdisp.aspx page. As you can see from the example above, this is a SharePoint-specific meta tag, which has two important attributes:
- ControlId – This attribute provides the unique identifier that will be referenced by any delegate control implementations which will tie them to this location.
- Scope – This attribute indicates the feature scope where SharePoint will look for delegates.
This meta-tag provides us with a point to hook up our own custom user controls to be included with the default SharePoint content, which we will call our “custom delegate control”. The most common method of implementing a custom delegate control is through the use of features containing control templates. Let’s start by looking at this in more detail. All SharePoint features live in the TEMPLATE\FEATURES directory within the 12-hive, commonly:
c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\FEATURES
Each feature is defined within a subdirectory, by way of an xml definition. The top-level file is always called feature.xml, and it contains the actual definition of the feature properties, such as:
Title=”User Profile Details”
Since this post is NOT about features, I won’t go into too much detail here. Rather, it is important to note that the Scope attribute defined here MUST match the Scope attribute defined by the SharePoint:DelegateControl reference. Possible values for Scope include:
- Web Application
- Site Collection
- Web Site
You will also notice that within the feature.xml definition, there is reference to an Elements.xml file. This file further defines the feature by referencing any external files or assemblies that are used by the feature. An example of this Elements.xml file…
<Control Id=”ProfileRedirection” Sequence=”95″ ControlSrc=”~/_controltemplates/UserProfileRedirect.ascx”/>
Notice that this example references our custom delegate control, located within the control templates directory. The Elements.xml can also point to an assembly, but we won’t go into that here. There are two important attributes to make note of in reference to SharePoint delegate controls:
- Id – This MUST match the ControlId attribute as defined in the SharePoint delegate control definition.
- Sequence – This attribute must be an integer value, and is used in the case where multiple delegate controls have been defined. The lowest sequence number with matching ControlId is always used.
So, we have our feature defined, and we have a custom delegate control defined that we want to be a delegate. Now what? Well, all we have to do is install the feature, and then SharePoint takes care of all the ControlId matching for us. Features are installed via one of the following methods:
- Manually – Installation can be performed manually by creating the feature directory within c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\FEATURES, placing the xml files within that directory, and running the following command:
stsadm.exe –o installfeature –filename [your feature dir]\feature.xml
- Using Solutions – You can also install the feature as part of a solution, by referencing it in a solution’s manifest.xml as follows…
In addition to creating and activating this feature, the actual .ascx file must exist in the location specified. It can be copied to the CONTROLTEMPLATES directory manually, but a better idea is to wrap the feature up as a solution, since solution packages can also deploy files.
<TemplateFile Location=”CONTROLTEMPLATES\UserProfileRedirect.ascx” />
These files would now all be packaged as a solution (.wsp) in the usual way with makecab.exe. When the solution is deployed, the file will be copied to the right place on all the web front-ends in your farm, and when the feature is activated
Once we have our feature in-place (via either method above), we just need to install and activate it. The easiest method for all features scopes is to activate using the command line, as follows:
stsadm -o installfeature -filename [feature dir]\feature.xml
stsadm -o activatefeature -filename [feature dir]\feature.xml -url [site-url]
Adding CSS Code into a Delegate Control using ASPX Pages
when creating an aspx page for instance with the SP Designer and you don not wonna add code in separte file use the code below:
<asp:Content id=”MyContent” runat=”server” contentplaceholderid=”PlaceHolderAdditionalPageHead“>
- I can now override which control a page should load without having to go back, edit the template and redeploy
- By using a feature scoped at ‘Web’, I can effectively use a different page header for different areas of my site without requiring different templates or code. (Note I’ve not tested this extensively, but since the <Control> element can be used at scope Web, Site, WebApplication or Farm, this should be perfectly feasible.)
- I can use any standard .Net user control or server control, so for anybody familiar with Jan Tielen’s SmartPart, this provides similar capability.
In terms of functionality, there’s a couple of other things I want to highlight:
- Parameters can be passed to the control via the declaration on the page. To read these, the control’s implementation should walk up the control tree to get the values. An example would be:
- By adding AllowMutiple=“true“ to the declaration, you can make the Delegate Control load more than one user/server control. For instance, you might create a control that emits keywords based on where the user is in the navigation. It might also emit other metatags that allow the site’s internal search engine to do a better job of indexing the site.
- As mentioned earlier, many of the controls used on default.master are loaded using the Delegate Control. These include global links such as My Site/My Links and the publishing console. So using this approach, customizing the publishing console is a simple matter of providing a replacement .ascx and creating a feature
Delegate controls are an important option for creating solutions that can be mixed and matched with other options. The ability to isolate one feature on a site from another feature can be an important tool in the SharePoint developer’s toolbox.