Last week I was trying to enable variations using a feature in SharePoint, but I soon realized that I had a problem because Microsoft decided to make all the variation-class internal. So that shouldn’t be a problem, why not use reflection. That didn’t work either, so back to the good old Lutz Roeder’s Reflector to see what’s going on. I soon found out that variations are dependent on 2 hidden lists (VariationSettings, VariationLabels), both lists can be found using the AllProperties of the root web:
using (SPSite site = new SPSite("http://localhost"))
{
using (SPWeb rootweb = site.RootWeb)
{
string _VarRelationshipsListId = rootweb.AllProperties["_VarRelationshipsListId"].ToString();
string _VarLabelsListId = rootweb.AllProperties["_VarLabelsListId"].ToString();
SPList VariationLabels = rootweb.Lists[new Guid(_VarLabelsListId)];
SPList VariationSettings = rootweb.Lists[new Guid(_VarRelationshipsListId)];
}
}
The variationlabels list contains a listitem for each variation that is available on the site, just add a new listitem to the list (make sure there is only one listitem that has the field “Is Source” set to true):
SPListItem variation = VariationLabels.Items.Add();
variation["Hierarchy Is Created"] = false;
variation[SPBuiltInFieldId.Title] = "EN";
variation["Description"] = "English";
variation["Flag Control Display Name"] = "English";
variation["Language"] = "en—US";
variation["Locale"] = 1033;
variation["Hierarchy Creation Mode"] = "Publishing Sites and All Pages";
variation["Is Source"] = false;
variation.Update();
The variationsettings are a little bit different, the settings are saved to the propertybag of the rootfolder of the list:
VariationSettings.RootFolder.Properties["SourceVarRootWebTemplatePropertyName"] = “sitetemplate#0”;
VariationSettings.RootFolder.Properties["EnableAutoSpawnPropertyName"] = true;
VariationSettings.RootFolder.Properties["AutoSpawnStopAfterDeletePropertyName"] = true;
VariationSettings.RootFolder.Properties["UpdateWebPartsPropertyName"] = true;
VariationSettings.RootFolder.Properties["CopyResourcesPropertyName"] = true;
VariationSettings.RootFolder.Properties["SendNotificationEmailPropertyName"] = true;
VariationSettings.Update();
These settings where easy, but then came the hard part, how do I create the hierarchies since all logic is internally scoped. Then I had a brainwave, why not try the good old webclient… It works:
using (WebClient webClient = new WebClient())
{
byte[] response;
webClient.UseDefaultCredentials = true;
response = webClient.DownloadData(input.Url + "/_Layouts/VariationLabels.aspx");
//get viewstate and requestdigest from page
string viewstate = ExtractHiddenValue("__VIEWSTATE", Encoding.ASCII.GetString(response));
string requestdigest = ExtractHiddenValue("__REQUESTDIGEST", Encoding.ASCII.GetString(response));
//format the postdata
string postData =
String.Format("__VIEWSTATE={0}&__REQUESTDIGEST={1}&__EVENTTARGET={2}&__EVENTARGUMENT={3}",
viewstate, requestdigest,
"ctl00$PlaceHolderMain$ctl00$RptControls$variationLabelsCreateHierarchiesToolBarButton",
"");
//send postdata to server
webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
webClient.UploadData(input.Url + "/_Layouts/VariationLabels.aspx", "POST",
Encoding.ASCII.GetBytes(postData));
}
Now I was finally able to create the hierachies in my build-script.