The K2 Pirate

July 20, 2011

Embedding Office Web App frame in a SharePoint page, dynamically

Filed under: General — hoshy @ 12:28 pm

I was looking for a way to embed a Word document in to my SharePoint page.  It seems the with Windows Live, this is allowed – but what if the documents are stored locally on a SharePoint 2010 Serve with Office Web Apps enabled? No. The URL doesn't allow for embedding, it detects the iframe and gives an error.

Looking around I found this post, it describes how to use the source of the WordViewer.aspx to grab the iframe for the actual document, this will then allow you to embed the document, but there is a problem.  The source for the iframe is a URL that looks something like this:

http://portal.denallix.com/Sites/DocumentApprovalCase/WordViewerFrame.aspx?d=F01fa671c0367476c94cf7159cdd4363eme27788ac7945483ab227dcbf558bce4fme45d2577bbde4734aa37e73babe4af3bm&source=http%3a%2f%2fportal.denallix.com%2fSites%2fDocumentApprovalCase%2fDocuments%2fProjektverfahrensanweisungen.docx

Now in my case I had a dynamic SharePoint site that needed to be provided a parameter for which document to display. At first glance it seems simple to URL encode the source parameter and easily embed any document.  This is not the case.  What's actually going on is that the 'd' parameter is an encoded reference tot he document location and it's this that must be set correctly.

I embarked on a little session of Reflection (big R for Red Gate, not little r, where I might contemplate my life as a rock star).

I discovered that the requried 'd' parameter is simple a concat of four GUIDs of the site, web, library, and file IDs, prefixed with an F (O for a folder).

Internally MS's code refers to this encoding as a "String Representation".  Here's some example code for the SharePoint Object Model to generate it from a URL, via an SPWeb.  You should probably choose a better way to implement this but here are the fundamentals:

    public class OfficeWebAppUtil
    {
        public static string GetWordViewerURL(string url)
        {

            url = HttpUtility.UrlPathEncode(url);

            using (SPSite site = new SPSite(url))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPFile file = web.GetFile(url);
                    string rep = StringRepFromItem(file);
                    return web.Site.Url + "/_layouts/WordViewerFrame.aspx?d=" + rep;
                }
            }
        }

        protected static string StringRepFromItem(SPFile item)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("F");
            builder.Append(item.Web.Site.ID.ToString("N"));
            builder.Append('m');
            builder.Append(item.Web.ID.ToString("N"));
            builder.Append('m');
            builder.Append(item.UniqueId.ToString("N"));
            builder.Append('m');
            return builder.ToString();
        }
    }

As for the soruce parameter – you might want to append that also as this is where you will be redirected to if you close the document or click the popout icon.

I'm sure the same technique will work for other document types.  If I get some time I'll wrap this in to a web part that can handle different document types… maybe :)

Cheers,

Hoshy, the K2 Pirate ;-)

Powered by WordPress