Programmatically Create Variation for a Publishing Page

Wow, have I ever spend time trying to figure this one out. There seems to be nothing, and I mean nothing out on the web that would explain how you would go about programmatically creating a page’s variation in SharePoint. The scenario I have is the following, we have users copying HTML pages from a legacy site into SharePoint using the Explorer View. An event receiver has been defined on the SharePoint Pages library that will go and read the file’s content, clean its HTML code, remove any PHP or Javascript code in it, and then convert it to a SharePoint Publishing Page (.aspx). Since we use a naming convention that uses a –e or –f at the end of a page’s name to determine if its content is English or French, it is very easy for me to determine where the variation page will be located.

 

Variations are created by a Timer job in SharePoint. This timer job uses a special king of JobDefinition called, the SPWorkItemJobDefinition. Think of it as a service ticket that is created and stored in the SharePoint content database, only to be picked up and processed by the timer job at a certain interval. All we need to do then, is to figure out a way to create such a Work Item and have it stored back in the content Database, but without interacting with the DB directly! Only by using the SharePoint Object Model. SPWorkItemJobDefinition is a generic class, and the only way to specify what type of work item we want to create, is by passing it a GUID. The type of work item that we are looking for in our scenario is named “CreateVariationPageJobDefinition” and has a GUID of 726dd8f-0e23-4c35-88b5-4fba39482515.

Work Item Name Work Item GUID
CreateVariationPageJobDefinition 726dd8f-0e23-4c35-88b5-4fba39482515

 

Work Items are added to the database by calling the SPSite.AddWorkItem() method on the Page’s parent Site Collection. Calling the following method will do exactly what we are looking for:

string textLoad = @”<WorkItem><PageTitle>Variation Page’s Title</PageTitle><Description>My Variation Page’s Description</Description><PageLayoutName>ArticleLeft.aspx</PageLayoutName>

<VariationLabel>fra</VariationLabel>

<DestPageName>variationpage.aspx</DestPageName><IsCopy>True</IsCopy>

<SourcePageUrl>http://mysite/Pages/mycurrentpage.aspx

</SourcePageUrl></WorkItem>”;

 

Guid webId = SPContext.Current.Web.ID; // Id of the current web in which the Publishing Page exists (not the variation web).

Guid rootWebId = SPContext.Current.Site.RootWeb.ID; // ID of the Site Collection’s root Web

int itemId = SPContext.Current.ListItem.ID; // Id of the publishing page itself. ID in this case is an autonumber representing the order in the list;

int userId = SPContext.Current.Web.CurrentUser.ID;

 

VariationHandler.AddWorkItem(properties.WebUrl, properties.Web.ID, properties.OpenSite().RootWeb.ID, properties.ListItem.ID, properties.Web.CurrentUser.ID, textLoad

 

SPSecurity.RunWithElevatedPrivileges(delegate()

{

using (SPSite site = new SPSite(siteUrl))

{

site.AddWorkItem(Guid.NewGuid(), System.DateTime.Now, new Guid(“726ddd8f-0e23-4c35-88b5-4fba39482515”), webId, rootWebId, itemId, true, Guid.Empty, Guid.Empty, userId, null, textLoad, Guid.Empty);

}

});

 

The Text Payload information is really what contains the magic. It tells the timer job what’s the name of the variation page, what its name is going to be in the variation site, what variation label to create it under, and adds a pointer to the current page to ensure proper linkage between the root label and the variations one. By default, the variation page timer job is set to execute every 2 minutes, so you’ll need to be patient if you’re trying to create a lot of pages at once.

SeaDragon View WebPart – Innovation at its Best

This project is now its own Codeplex project

Remember Microsoft Live Labs? They used to be a bunch of innovative guys down at Microsoft. Their team got dismantled a few years ago, but before it happened, they managed to release a bunch of interesting innovations. You probably recall project PhotoSynth, which provided a way for users to stich images together and recreate a 3d environment. Another very interesting project they managed to release was called SeaDragon, which allows users to do Deep Zooming on a particular image. The original version of the tool was using Silverlight (remember that name?). However, a side project to make it web based was initiated about 2 years ago. The project is called Seadragon AJAX

(http://gallery.expression.microsoft.com/SeadragonAjax ).

Even though there hasn’t been much work on the project for quite a long time, I decided I’d give it a go, and see how well I could integrate it with SharePoint. For those not familiar with the concept of Deep Zooming, it basically is the process of blowing up an image into several smaller pieces, and improving the display Quality of each of the pieces. The outcome of this process is an XML file associated with a bunch of folder name 0 to X each containing a matrix of smaller images. You can read more on the concept of Deep Zooming at http://msdn.microsoft.com/en-us/library/cc645050%28VS.95%29.aspx .Microsoft provides a little tool called Deep Zoom Composer which is a spin-off of the Expression suite, and which allows you to create the deep zoom files associated with an image.

My idea was to create a wrapper inside of a SharePoint WebPart that would allow users to display a Deep Zoom image. The deep zoom images could be hosted anywhere on the web, but in my case I decided to upload them directly inside of a SharePoint document library. My web part exposes 3 persistent properties: the url to the deep zoom xml file, the width of the wrapper, and its height. Now, the Seadragon AJAX project is all Javascript based, so what about accessibility? Simple enough, my web part has been made smart enough so that if javascript is disable on the client’s PC, then a static version of the image without the deep zoom ability should be provided.

 

You can see a demo of the describe web part on my blog at:

http://nikcharlebois.com/Pages/Demo-seadragon.aspx .

Please note that the version is using does not fallback to a static image when javascript is disabled. I have another version of this web part that is accessible, all you have to do is let javascript write the required Div tags for the SeadragonViewer, and provide the static image alternative via a <noscript> tag. I’ve also uploaded the Source code for the webpart. You can find it at:

http://www.ignitesoft.ca/Blogs/Nik/Documents/Source%20Code/SeaDragonViewer.zip

 

Enjoy