Part 1 - The BasicsPart 2 - User InterfacePart 3 - TriggersPart 4 - Timer JobsPart 5 - Configuration OverviewPart 6 - Configuration InternalsPart 7 - Variation Hierarchy CreationPart 8 - Creating Page VariantsPart 9 - Creating Site VariantsPart 10 - Restructuring the HierarchyPart 11 - Variations Fixup ToolPart 12 - CustomizationPart 13 - LoggingPart 14 - TroubleshootingPart 15 - "View Changes" ButtonPart 16 - Translation SupportPart 17 - MOSS 2007 vs. SP 2010Part 18 - FAQ
This module explains supported ways to implement customizations in the variation system.
You can apply the following types of customization:
The following actions are performed while creating the variation hierarchy:
If a user navigates to the Variation root site, SharePoint Server 2010 looks up the configure Welcome Page of the site and redirects to the VariationRoot.aspx page. As this page is based on VariationRootPageLayout.aspx, it executes the logic in the page layout file.
The VariationRootPageLayout.aspx page layout contains a reference to a file called VariationsRootLanding.ascx file, which resides on the file system in the …\14\template\controltemplates folder. The VariationsRootLanding.ascx file implements the logic, which redirects the user to a Variation site.
The default logic used in the VariationsRootLanding.ascx file is to redirect the user to the Variation site that matches the browser's accepted languages.
If you want the Variation root landing page logic to redirect the user to a Variation site that is not based on the accept language, you can do this in one of three ways. Each option has its own advantages and disadvantages, and you should consider them carefully before deciding which approach to use:
This is the quickest way to edit the logic, as you only have to edit the logic in the VariationsRootLanding.ascx file in the file system of each Web front-end (WFE) server.
All site collections in the farm will use the same logic to redirect to a variation label.
The change has to be done on all WFEs and if a change is required, it is necessary to update the files on all WFEs.
This method requires changing the reference to user control in the VariationRootPageLayout.aspx using SharePoint Designer.
You can easily update the logic by replacing the logic in the custom ascx file on the file system.
Each site collection can have a different logic for the redirection.
The copy has to be created on all WFEs and if a change is required, it is necessary to update the files on all WFEs.
You have to update the VariationRootPageLayout.aspx to reference the updated user control.
This can be achieved by copying and adjusting the content from the VariationsRootLanding.ascx file into the VariationRootPageLayout.aspx in the Master Page and Page Layouts Gallery.
Like the previous approach, this approach also provides rapid customization through direct editing.
Changes have to be done only at one single location as the logic is in the database.
To complete this process, it is required to modify the web.config to allow inline code in the VariationRootPageLayout.aspx page.
<SharePoint> <SafeMode ... > <!-- Enable ASP.NET compilation for variation root logic --> <PageParserPath VirtualPath="/_catalogs/masterpage/VariationRootPageLayout.aspx" CompilationMode="Always" AllowServerSideScript="True" AllowUnsafeControls="False" IncludeSubFolders="False"/> </PageParserPaths> </SafeMode> </SharePoint>
An additional customization might be to place the logic into a custom assembly and deploy this using a feature into the Global Assembly Cache of all machines. Then you can reference this custom code either from the user control or directly from the VariationRootPageLayout.aspx page.
Many websites allow a reader to switch to a different language version of the same page using a hyperlink - either textual or as an image (e.g. the country flag).
SharePoint 2010 provides a framework to implement the required functionality quickly:
Each of the default master pages contains a reference to a file called VariationsLabelMenu.ascx, through a DelegateControl element in their markup:
<SharePoint:DelegateControl runat="server" ID="GlobalDelegate0" ControlId="GlobalSiteLink0" />
The publishing feature registers the DelegateControl GlobalSiteLink0 element in …\14\TEMPLATE\FEATURES\Publishing\VariationsFlagControl.xml. This XML file points to the VariationsLabelMenu.ascx file, which causes all sites provisioned with the publishing feature to have the rendering provided by VariationsLabelMenu.ascx. This also causes the master pages for all publishing site collections in the server farm to contain the same rendering provided by VariationsLabelMenu.ascx.
<!-- _lcid="1033" _version="14.0.4750" _dal="1" --> <!-- _LocalBinding --> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <Control Sequence="50" Id="GlobalSiteLink0" ControlSrc="~/_controltemplates/VariationsLabelMenu.ascx"> </Control> <Control Sequence="50" Id="VariationsFlagControl" ControlSrc="~/_controltemplates/VariationsLabelMenu.ascx"> </Control> </Elements>
As you can see the same user control is registered with two different control Ids: GlobalSiteLink0 and VariationsFlagControl. It does not matter which Id you use in your master pages - both will work.
Because the Delegate controls are the same for all publishing sites in all site collections, they all reference the same user control on the file system, the rendering cannot vary from site collection to site collection with default setup.
The VariationsLabelMenu.ascx file needs to contain the logic to render variation label menu on the page. Per default only the VariationDataSource control is embedded in this control but not a rendering control to leverage this data source. So per default no variation labels menu is displayed.
In order to display the variation labels menu it is required to update the VariationsLabelMenu.ascx and add a reference to a rendering control for the data source.
We will discuss supported methods to customize this control in the next sections.
The VariationDataSource control is not a rendering control. It acts as data source for other web controls, which support data binding like a Repeater, or a DataList control.
It provides information about peers of the current page in other variation labels.
This data source can be utilized by different controls like an ASP.NET Repeater or a DataList control or the VariationsLabelEcbMenu shipped with SharePoint.
<cms:VariationDataSource id="LabelMenuDataSource" LabelMenuConfiguration="1" Filter="" runat="server"/>
The VariationDataSource control supports three different operation modes using the LabelMenuConfiguration attribute:
The variation data source supports filtering on the label result set. If e.g. administrative labels exist in the hierarchy, which should not be exposed to users, then you can create a regular expression filter on the label name to exclude them from the view, which means that the data source will not return links to peer pages in the filtered labels. A simple filter could be "^\w". This filter will only display labels which start with alphanumeric characters (a-z, A-Z, 0-9). Labels starting (e.g.) with a special character like "-" will not be displayed.
We will discuss how to use the VariationDataSource with a rendering control in the next sections.
In the previous section, we discussed the different instances involved in rendering a variation label menu. However, without customization no menu is displayed, as no rendering control is included in the out-of-the-box user control.
Different customizations are possible - each with individual advantages and disadvantages:
This is the quickest way to edit the logic, as you only have to edit the logic in the VariationsLabelMenu.ascx file in the file system of each front-end Web server.
All site collections in the farm will use the same logic to render the variation label menu.
This method requires changing the reference to the user control in the master page using SharePoint designer and/or to register a new control for the delegate control using a custom feature.
You can easily update the logic by replacing the logic in the custom .ascx file on the file system.
This method also requires changing the reference to the user control in the master page using sharepoint designer and/or to register a new control for the delegate control using a custom feature.
Like the previous approach, this approach also provides rapid customization through direct editing using SharePoint designer.
To complete this process, it is required to modify the web.config to allow inline code in the VariationLabelMenu.ascx user control in the master page gallery.
<SharePoint> <SafeControls> <!-- Marks the VariationsLabelMenu.ascx as safe. --> <SafeControl src="http://blogs.technet.com/_catalogs/masterpage/VariationsLabelMenu.ascx" Safe="True" AllowRemoteDesigner="True" /> </SafeControls> <SafeMode ... > <!-- Marks VariationsLabelMenu.ascx for compilation. --> <PageParserPaths> <PageParserPath VirtualPath="/_catalogs/masterpage/VariationsLabelMenu.ascx" CompilationMode="Always" AllowServerSideScript="True" AllowUnsafeControls="False" /> </PageParserPaths> </SafeMode> </SharePoint>
After we have discussed different way to modify the VariationsLabelMenu.ascx we need to look into the specific changes that have to be done to this file to enable rendering of the variation label menu.
Per default, the content of the VariationsLabelMenu.ascx looks as follows:
<%@ Control Language="C#" %> <%@Assembly Name="Microsoft.SharePoint.Publishing, Version=220.127.116.11, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%> <%@Register TagPrefix="CMS" Assembly="Microsoft.SharePoint.Publishing, Version=18.104.22.168, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.Publishing.WebControls"%> <cms:VariationDataSource id="LabelMenuDataSource" LabelMenuConfiguration="1" Filter="" runat="server"/>
As you can see, the VariationDataSource control is included but no rendering control is available to render links to peer pages or sites.
In SharePoint 2007, the file looked slightly different:
<%@ Control Language="C#" %> <%@Assembly Name="Microsoft.SharePoint.Publishing, Version=22.214.171.124, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%> <%@Register TagPrefix="CMS" Assembly="Microsoft.SharePoint.Publishing, Version=126.96.36.199, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.Publishing.WebControls"%> <%-- <cms:VariationsLabelEcbMenu id ="varlabelmenu1" DataSourceID="LabelMenuDataSource" DisplayText="<%$Resources:cms,VariationLabelMenuTitle%>" IsCallbackMode="true" runat="server" /> --%> <cms:VariationDataSource id="LabelMenuDataSource" LabelMenuConfiguration="1" Filter="" runat="server"/>
As you can see, the user control contained a commented reference to the VariationsLabelEcbMenu, which utilized the VariationDataSource.
In SharePoint 2010, the VariationsLabelEcbMenu is still available but marked as deprecated.
That means your existing applications still work (at least with the current version) but it is recommended to use a different control for future implementations.
Many customer have special needs to render the variation labels (e.g. to render a flag beside the label name) which cannot be done with this control.
Using the standard ASP.NET controls gives much more control of the generated html.
The main difference between these two controls is that the Repeater allows a more flexible formatting while the DataList renders each entry in a table rows or table columns.
Both controls use templates and data binding for the rendering.
Here is a simple example for the Repeater control:
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="LabelMenuDataSource" EnableViewState="False"> <ItemTemplate> <a href="<%# DataBinder.Eval(Container.DataItem, "NavigateUrl") %>"> <%# DataBinder.Eval(Container.DataItem, "DisplayText") %></a> </ItemTemplate> <SeparatorTemplate> | </SeparatorTemplate> </asp:Repeater>
Each Container object in the item template supports the following public properties:
Each of these properties can be used inside the ItemTemplate for the rendering of the current Variation link node.
The Repeater control supports two different templates: one to be used for each of the elements in the collection the repeater iterates over, and one, which will be used as a separator between the elements.
In the sample above, we just use a vertical bar as separator, which is a nice way to separate entries in a horizontal list. Alternatively, you can embed the repeater in a html table and use column/row end/start tags in the separator template.
After implementing a custom label menu using the VariationDataSource and one of the ASP.NET controls you will notice the following problem when using the View or Edit properties from the ribbon (callstack enabled and custom errors disabled in web.config to get a better error message):
This error occurs as with all controls, which perform databinding on first load - including the VariationsLabelEcbMenu if CallbackMode is disabled.
Note: The IsCallbackMode attribute of the VariationLabelEcbMenu controls whether databinding is performed with every page request or only if the user clicks the dropdown rendered by the menu.
See my previous post for more details and workaround of this problem.
Web Parts are a black box for the content deployment and migration API. Only the web part itself knows what type of content is stored inside it. When variating pages from source to target it might be that the content of the web part has to be adjusted to work correct at the new location.
The content deployment and migration API cannot directly perform these modifications as it does not know which operations to perform to make the web part content compatible with the new location.
To overcome this problem the developer of a web part can implement the IWebPartVariationUpdate interface. Using this interface it is possible to implement an Update method which can then be called by the variation feature after the page holding the web part has been replicated to the target label to ensure that the web part can fix its internal data.
From the web parts shipped with SharePoint only the ContentByQueryWebPart and the TableOfContentsWebPart implement this interface.
You can apply event receivers to the Sites or Pages libraries of the target label - e.g. through Feature stapling - and perform specific operations.
A good example of such a modification has been demonstrated by Vamsi Krishna Rallabhandi on his recent blog post: