Skip to main content

Weblog Ton Stegeman [MVP]

Go Search
Home
  

ODC 2008
If you have a question or suggestion, please contact me through Windows Live Messenger.
My status: .

If I am not online, please send me an e-mail.
Weblog Ton Stegeman [MVP] > Posts > Creating MOSS pages using RPC
Creating MOSS pages using RPC

In one of my current projects, we have a publication process in which we read content from Lotus Notes. Users do some editting and then publish the items to MOSS. In a previous item, I showed how I read the content from Notes. In this post I will show you how we publish the items to MOSS. At first it sounds easy, but a big requirement we had was to do this without deploying server side code. To do this, we created a Windows application. This application posts pages in SharePoint using Frontpage RPC. The Windows application creates a publishing page of the specified page layout, and adds the content to that page.

A good place for a quick start on RPC is the RPC test page by the IW Kid. You can find it here. The referenced zip file WSS RPC.zip contains a test page with several examples of RPC calls. This should get you started pretty quickly. The sample code below is a simplified version of the code in the testpage. I stripped it just for demonstration purposes.

Another way to get a better understanding of how RPC works it to install Fiddler and use SharePoint Designer. In Fiddler you will find the calls and the responses.

The rest of this post decribes the most important parts of the code. You can find the full code in this zip file.

Step 1 - Create the user interface and the MOSSPage object.

The first thing I did was to create a user interface for the windows application. It is shown in the screenshot below. The user enters a name for the page, a title and the content for the page. The url of the site to which the page will be published is entered. The last stap is to edit a reference to a page layout. In SharePoint, the between a page and its page layout is a Hyperlink field on the Pages library. Therefore you need to supply the reference to the page layout as a  hyperlink value, which looks like this:

http://moss/_catalogs/masterpage/ArticleLeft.aspx, Article page with image on left

It is composed of the full links to the aspx, followed by a "," separator and the name of the page layout.

image

When the user clicks the "Publish" button, a new object of type MOSSPage is created and the properties are set:

After that the Publish method is called:

MOSSPage page = new MOSSPage();
page.Name = textBoxName.Text;
page.PageLayout = textBoxPageLayout.Text;
page.Title = textBoxTitle.Text;
page.Content = textBoxContent.Text;
textBoxResult.Text = page.Publish(textBoxSite.Text);

Step 2 - Publication

The publish method of the MOSSPage object generates a dictionary of properties that will be added to the RPC request when it is submitted. The key of the property is the name of the property as it needs to be supplied to the RPC request.

Dictionary<string, string> properties = new Dictionary<string, string>();
properties.Add("vti_title", Title);
properties.Add("PublishingPageLayout", PageLayout);
properties.Add("PublishingPageContent", Content);
byte[] fileContents = System.Text.Encoding.ASCII.GetBytes(emptyASPX);

return UploadDocument(siteUrl, string.Format("{0}.aspx", Name), fileContents, properties);

After creating the dictionary it creates a byte array that contains the content of the page. A page in SharePoint is nothing more than an ASPX document in a document library, with custom metadata. Therefore you need to supply the contents of the ASPX file that the RPC request will submit. For a publishing page, this looks like this:

private const string emptyASPX =
"<%@ Page Inherits=\"Microsoft.SharePoint.Publishing.TemplateRedirectionPage,
Microsoft.SharePoint.Publishing,Version=12.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c\" %>
<%@ Reference VirtualPath=\"~TemplatePageUrl\" %> <%@ Reference VirtualPath=\"~masterurl/custom.master\" %>";

It calls the UploadDocument method, that creates and submits the RPC call.

Step 3 - Upload

UploadDocument first creates the RPC request. First it initializes and encodes a number of variables.

Uri uri = new Uri(url);

// Init variables.
string method = "put document:12.0.4518.1016";
string service = uri.AbsolutePath;
string document = "[document_name={0};meta_info=[{1}]]";
string documentName = string.Format("{0}/{1}", pagesLibrary, fileName);
document = String.Format(document, documentName, GetMetaInfo(metaInfo));
string rpcString = "method={0}&service_name={1}&document={2}&put_option=createdir";

// Encode variables.
method = HttpUtility.UrlEncode(method);
service = HttpUtility.UrlEncode(service);
document = HttpUtility.UrlEncode(document);

// Get the RPC call data
rpcString = String.Format(rpcString, method, service, document);
byte[] callData = GetRPCCall(rpcString, fileContents);

In this snippet, the variable metaInfo contains the dictionary of properties that was created in the previous step. The are added to the rpcString by the function "GetMetaInfo":

private static string GetMetaInfo(Dictionary<string, string> properties)
{
    if (properties == null) 
        return string.Empty;
    StringBuilder sb = new StringBuilder();
    foreach (KeyValuePair<string, string> property in properties)
    {
        if (property.Value != null)
        {
            string data = EscapeVectorChars(property.Value.ToString());
            sb.AppendFormat("{0};SW|{1};", property.Key, data);
        }
    }
    return sb.ToString().TrimEnd(';');
}

This function escapes a number of characters and returns one big string that contains all property names and values. For one property, this string looks like this:

meta_info=[vti_title;SW|Testpage published by using Frontpage RPC]"

It contains the name of the property (please note, for this "Title" this is "vti_title" instead of "Title"). After the pipe symbol, it contains the value. In between the two you will find (in this case) the value "SW". The S is used for the datatype (always string in my simplified example).  You can find the code to escape the characters in the ZIP file referenced before.

After setting up the rpcString, our UploadMethod function combines the contents of the ASPX file that will be submitted and the RPC call to a byte array:

private byte[] GetRPCCall(string rpcString, byte[] fileContents)
{
    string callString = rpcString;
    callString.Replace(".", "%2e");
    callString.Replace("_", "%5f");

    byte[] callBytes = System.Text.Encoding.UTF8.GetBytes(callString);
    byte[] data = new byte[callBytes.Length + fileContents.Length + 1];
    callBytes.CopyTo(data, 0);
    data[callBytes.Length] = 0x0A;
    fileContents.CopyTo(data, callBytes.Length + 1);
    return data;
}

Now our call is ready to be submitted. We do this by using a WebClient object:

// Send the request.
byte[] result = null;
using (WebClient client = new WebClient())
{
    client.Credentials = System.Net.CredentialCache.DefaultCredentials;
    client.Headers.Add("Content-Type", "application/x-vermeer-urlencoded");
    client.Headers.Add("X-Vermeer-Content-Type", "application/x-vermeer-urlencoded");
    result = client.UploadData(url + "/_vti_bin/_vti_aut/author.dll", "POST", callData);
}

// Return the result.
return System.Text.Encoding.UTF8.GetString(result);

The result of the call returned to the user interface.

Step 4 - Test

Now that we have completed our publication process, we can test the application. After clicking the Publish button we will find the page and its content in the Pages library that we specified:

image

Below you will find an example of the output that is returned by our POST command. Just to give you an idea of what is looks like.

<html><head><title>vermeer RPC packet</title></head>
<body>
<p>method=put document:12.0.0.6219
<p>message=successfully put document 'Pages/Testpage2.aspx' as 'Pages/Testpage2.aspx'
<p>document=
<ul>
<li>document_name=Pages/Testpage2.aspx
<li>meta_info=
<ul>
<li>PublishingPageContent
<li>SW|content
<li>vti_rtag
<li>SW|rt:C45F9E3B-4F82-46D8-8757-1577D94E4A9D@00000000001
<li>vti_etag
<li>SW|&#34;&#123;C45F9E3B-4F82-46D8-8757-1577D94E4A9D&#125;,1&#34;
<li>vti_filesize
<li>IR|279
<li>vti_parserversion
<li>SR|12.0.0.6219
<li>vti_modifiedby
<li>SR|TST_MOSS2007&#92;administrator
<li>vti_timecreated
<li>TR|20 May 2008 19:55:14 -0000
<li>vti_title
<li>SW|Title for second test page
<li>vti_charset
<li>SR|windows-1252
<li>ContentTypeId
<li>SW|0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900EF933E554CA5E54FAC89BEC91C15C93D
<li>vti_sourcecontrolmultiuserchkoutby
<li>VR|TST_MOSS2007&#92;&#92;administrator
<li>vti_timelastmodified
<li>TR|20 May 2008 19:55:14 -0000
<li>PublishingPageLayout
<li>SW|http://moss/_catalogs/masterpage/ArticleLeft.aspx, Article page with image on left
<li>vti_author
<li>SR|TST_MOSS2007&#92;administrator
<li>vti_sourcecontrolcheckedoutby
<li>SR|TST_MOSS2007&#92;administrator
<li>vti_sourcecontroltimecheckedout
<li>TR|20 May 2008 19:55:14 -0000
<li>vti_sourcecontrolversion
<li>SR|V0.1
<li>vti_sourcecontrolcookie
<li>SR|fp_internal
<li>vti_linkinfo
<li>VX|UJUS|/_catalogs/masterpage/ArticleLeft.aspx UHUS|~masterurl/custom.master UHUS|~TemplatePageUrl
</ul>
</ul>
</body>
</html>

Comments

There are no comments yet for this post.
Items on this list require content approval. Your submission will not appear in public views until approved by someone with proper rights. More information on content approval.

Title


Body *


Your city *


Type the name of the city you live in (making it easier to handle spam...)

CurrentDate *

Select the current date (see if this gives me fewer spam...)
Attachments

 Links

  SharePoint Object on CodePlex
  Screencast introducing SharePoint Objects
  Content by Type and Filter Web Parts on CodePlex
  Archive
  Archive (Calendar)

 My Latest Blog Posts

Scripting SharePoint 2007 setup: choices and conceptsUse SHIFT+ENTER to open the menu (new window).
Adventures in Visual Studio 2010: Migrate the Content By Type web part to SharePoint 2010Use SHIFT+ENTER to open the menu (new window).
Register SharePoint themes by using a featureUse SHIFT+ENTER to open the menu (new window).
SharePoint 2010 development on Windows 2008 Server R2 – Getting StartedUse SHIFT+ENTER to open the menu (new window).
New release SharePoint Objects: features and groupsUse SHIFT+ENTER to open the menu (new window).
Constructing the url to the SharePoint Edit Permissions pageUse SHIFT+ENTER to open the menu (new window).
Screencast: introduction to SharePoint ObjectsUse SHIFT+ENTER to open the menu (new window).
SharePoint 2007 and Reporting ServicesUse SHIFT+ENTER to open the menu (new window).
SharePoint Objects – Insight in usage of your SharePoint artifactsUse SHIFT+ENTER to open the menu (new window).
SharePoint 2007 Custom list schema and the Content Query Web PartUse SHIFT+ENTER to open the menu (new window).
SharePoint 2010 Silverlight Client Object Model – ExecuteQuery vs ExecuteQueryAsyncUse SHIFT+ENTER to open the menu (new window).
SharePoint 2010, the Client Object Models and Bing MapsUse SHIFT+ENTER to open the menu (new window).
Having fun with SharePoint 2010, Silverlight 3 and Bing MapsUse SHIFT+ENTER to open the menu (new window).
Connecting TFS 2010 projects to SharePoint sitesUse SHIFT+ENTER to open the menu (new window).
Adding a database to the SharePoint database Server using SPDatabaseUse SHIFT+ENTER to open the menu (new window).