Posted on March 23, 2008 10:53 by mcollins

Yesterday, in my flurry of posting activity all day long, we covered the Blogger API, the MetaWeblog API, and in a screencast I demonstrated how Microsoft Office Word 2007 would use the MetaWeblog API to communicate with the website and publish text and images to the website using operations from each of those APIs.

Today, we turn our attention to using Windows Live Writer and geting Windows Live Writer to work with our website.  While we could connect Windows Live Writer up to our website directly, just like we did with Word, there are some features supported by Windows Live Writer that make the content publishing experience much easier when the website supports it.

The first feature that we're going to implement to add support for Windows Live Writer is a protocol called Really Simple Discovery (RSD).  RSD is basically an XML document that is placed on your website (or in our case, will be generated by our website using an HTTP handler in ASP.NET).  The XML elements in the RSD document tell a client program such as Windows Live Writer where to locate the MetaWeblog publishing service.  The link to the RSD document is contained in the header of the home page for the blog or website that we're publishing to from Windows Live Writer.

At runtime, what will happen is that we'll start up Windows Live Writer and register a new blog or website with it.  Windows Live Writer will ask us for the URL to the home page for the blog or website, which we'll type in.  Windows Live Writer will download the contents of the home page and will look in the <head> section for an HTML element that will look similar to this:

   1: <html>
   2:     <head>
   3:         ...
   4:         <link rel="EditURI" type="application/rsd+xml"
   5:             title="RSD" href="http://localhost:9500/rsd.ashx"/>
   6:         ...
   7:     </head>
   8:     <body>
   9:         ...
  10:     </body>
  11: </html>

 

The <link> element in the HTML uses the rel attribute to identify the link for RSD.  Once a program such as Windows Live Writer finds this line, Windows Live Writer will be able to use the URL in the href attribute to locate the RSD document (or in our case, our HTTP handler).

While I could have created an XML file for RSD, I chose to go with creating an HTTP handler that will build the RSD document at runtime.  The reason why I chose to do this is that the URLs specified in the RSD document need to be absolute URLs for Windows Live Writer to locate the APIs correctly.  In my HTTP handler, I use the current request information to build the URL for the MetaWeblog API implementation.  Here's the code for the RSD HTTP handler:

   1: public class ReallySimpleDiscoveryHandler : IHttpHandler {
   2:     /// <summary>
   3:     /// Returns true to indicate that the HTTP handler can be reused for
   4:     /// multiple requests.
   5:     /// </summary>
   6:     public bool IsReusable {
   7:         get { return true; }
   8:     }
   9:  
  10:     /// <summary>
  11:     /// Handles the request and serves the RSD document to the client.
  12:     /// </summary>
  13:     /// <param name="context">
  14:     /// The <see cref="HttpContext"/> used to handle the current
  15:     /// request.
  16:     /// </param>
  17:     public void ProcessRequest(HttpContext context) {
  18:         string rootUrl = String.Format("{0}://{1}:{2}/",
  19:             context.Request.Url.Scheme, context.Request.Url.Host,
  20:             context.Request.Url.Port);
  21:  
  22:         XNamespace ns = "http://archipelago.phrasewise.com/rsd";
  23:         XDocument rsdDocument = new XDocument(new XElement(ns + "rsd",
  24:             new XAttribute("version", "1.0"),
  25:             new XElement(ns + "service", "Content Publishing 101"),
  26:             new XElement(ns + "engineLine", 
  27:                 "http://www.sogeti-phoenix.com"),
  28:             new XElement(ns + "homePageLink", rootUrl),
  29:             new XElement(ns + "apis",
  30:                 new XElement(ns + "api",
  31:                     new XAttribute("name", "MetaWeblog"),
  32:                     new XAttribute("preferred", "true"),
  33:                     new XAttribute("apiLink", rootUrl +
  34:                         "ContentPublishingService.ashx"),
  35:                     new XAttribute("blogID", "michael")),
  36:                 new XElement(ns + "api",
  37:                     new XAttribute("name", "Blogger"),
  38:                     new XAttribute("preferred", "false"),
  39:                     new XAttribute("apiLink", rootUrl +
  40:                         "ContentPublishingService.ashx"),
  41:                     new XAttribute("blogID", "michael")))));
  42:  
  43:         context.Response.Write(rsdDocument.ToString());
  44:     }
  45: }

 

I'm using the new LINQ XML support introduced in .NET 3.5 to build the RSD XML document.  The RSD that I am generating tells an RSD client that we support both the MetaWeblog API and the Blogger API, but the MetaWeblog API is preferred over the Blogger API.  The XML that this handler outputs looks like this:

   1: <rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd">
   2:   <service>Content Publishing 101</service>
   3:   <engineLine>http://www.sogeti-phoenix.com</engineLine>
   4:   <homePageLink>http://localhost:9500/</homePageLink>
   5:   <apis>
   6:     <api name="MetaWeblog" preferred="true" 
   7:         apiLink="http://localhost:9500/ContentPublishingService.ashx" 
   8:         blogID="michael" />
   9:     <api name="Blogger" preferred="false" 
  10:         apiLink="http://localhost:9500/ContentPublishingService.ashx" 
  11:         blogID="michael" />
  12:   </apis>
  13: </rsd>

 

One thing to note is that I thought that I read someplace that the blogID attribute in the RSD output isn't used, however when I tried this out I discovered that Windows Live Writer does use it to get the blogid value that it will use with the Blogger and MetaWeblog APIs.  This has important ramifications for using Windows Live Writer for your blog or website.

The main issue that will affect your website is if you were to build some sort of multi-blogger experience, or build a website with several subsites, each with their own sets of categories.  The way that Windows Live Writer requires and uses the blogID attribute means that you can't have one global RSD file that works for the entire site.  Each blog or subsite on your website will need to have its own RSD file.

Now that we have told Windows Live Writer how to find our content publishing service using RSD, it's not time that we help Windows Live Writer out by telling it what features that we support.  Windows Live Writer is actually a fully developed editing environment with a lot of features for creating new content to be published up to a website.  However, Windows Live Writer also knows that it can't be everything to everyone.  There are some features that Windows Live Writer does support that some blog engines and content management systems don't support.  So we have to help out Windows Live Writer from our website to tell WLW what features we do support.  We also want to go a step beyond that and help customize Windows Live Writer to give our content authors a few customizations to help them do their jobs of publishing content.  We can do all of this by providing Windows Live Writer with an XML manifest file that tells Windows Live Writer about our blog or website.

During the blog/website registration process with Windows Live Writer, Windows Live Writer will download our RSD file to find the location of the MetaWeblog API.  Windows Live Writer, like Microsoft Office Word 2007, will then make some calls to our website to make sure that the blog exists and to get the list of categories for the website.  Somewhere during the registration process, Windows Live Writer will look at our home page to also find a link to the manifest file for Windows Live Writer.  We will add this link right next to the RSD link in the header section of our home page:

   1: <html xmlns="http://www.w3.org/1999/xhtml">
   2: <head runat="server">
   3:     <title>Untitled Page</title>
   4:     <link rel="EditURI" type="application/rsd+xml" title="RSD"
   5:         href="http://localhost:9500/rsd.ashx" />
   6:     <link rel="wlwmanifest" type="application/wlwmanifest+xml"
   7:         href="http://localhost:9500/wlwmanifest.ashx" />
   8: </head>
   9: <body>
  10:     <form id="form1" runat="server">
  11:     <div>
  12:     
  13:     </div>
  14:     </form>
  15: </body>
  16: </html>

 

On line 6 is the link to our manifest file for Windows Live Writer.  I've chosen once again to implement this as an HTTP handler because at some point in the future I may choose to allow the website administrator to selectively configure which options the website should support.  For example, the website administrator may not want posts that have embedded JavaScript code in them, or <embed> elements.

Before I show you the source code for the HTTP handler and the resulting XML generated by it, you might want to pause and take a look at the manifest file specification for Windows Live Writer.  Here's the source code for my manifest file generator:

   1: public void ProcessRequest(HttpContext context) {
   2:     XNamespace ns = "http://schemas.microsoft.com/wlw/manifest/weblog";
   3:     XDocument xmlDocument = new XDocument(new XElement(ns + "manifest",
   4:         new XElement(ns + "options",
   5:             new XElement(ns + "clientType", "Metaweblog"),
   6:             new XElement(ns + "supportsScripts", "Yes"),
   7:             new XElement(ns + "supportsEmbeds", "Yes")),
   8:         new XElement(ns + "weblog",
   9:             new XElement(ns + "serviceName", "Michael's Blog"),
  10:             new XElement(ns + "homepageLinkText",
  11:                 "View Michael's Blog"),
  12:             new XElement(ns + "adminLinkText",
  13:                 "Manage Michael's Blog"),
  14:             new XElement(ns + "adminUrl",
  15:                 new XCData("http://localhost:9500/Admin")),
  16:             new XElement(ns + "postEditingUrl", new XCData(
  17:                 "http://localhost:9500/EditPost.aspx?postId={post-id}"))),
  18:         new XElement(ns + "views",
  19:             new XElement(ns + "default", "WebLayout"),
  20:             new XElement(ns + "view",
  21:                 new XAttribute("type", "WebLayout"),
  22:                 new XAttribute("src",
  23:                     "http://localhost:9500/WebLayout.aspx")),
  24:             new XElement(ns + "view",
  25:                 new XAttribute("type", "WebPreview"),
  26:                 new XAttribute("src",
  27:                     "http://localhost:9500/WebPreview.aspx")))));
  28:  
  29:     context.Response.Write(xmlDocument.ToString());
  30: }

 

Again, I used the new LINQ XML support to generate the XML for the Windows Live Writer manifest.  Here's what the generated XML looks like:

   1: <manifest xmlns="http://schemas.microsoft.com/wlw/manifest/weblog">
   2:   <options>
   3:     <clientType>Metaweblog</clientType>
   4:     <supportsScripts>Yes</supportsScripts>
   5:     <supportsEmbeds>Yes</supportsEmbeds>
   6:   </options>
   7:   <weblog>
   8:     <serviceName>Michael's Blog</serviceName>
   9:     <homepageLinkText>View Michael's Blog</homepageLinkText>
  10:     <adminLinkText>Manage Michael's Blog</adminLinkText>
  11:     <adminUrl><![CDATA[http://localhost:9500/Admin]]></adminUrl>
  12:     <postEditingUrl><![CDATA[
  13:         http://localhost:9500/EditPost.aspx?postId={post-id}
  14:     ]]></postEditingUrl>
  15:   </weblog>
  16:   <views>
  17:     <default>WebLayout</default>
  18:     <view type="WebLayout" 
  19:         src="http://localhost:9500/WebLayout.aspx" />
  20:     <view type="WebPreview" 
  21:         src="http://localhost:9500/WebPreview.aspx" />
  22:   </views>
  23: </manifest>

 

There are several important things to note from this manifest file, mostly on lines 3, 4, and 5.  First, on line 3, I am saying that my blog or website supports the MetaWeblog API, which I implemented in the earlier posts.  You might want to look again at the manifest specification to see what specific features that I am saying that I am supporting for Windows Live Writer.  On lines 4 and 5, I am extending this feature set to say that I'm going to allow new posts to have embedded JavaScript and embedded objects such as Silverlight or YouTube videos, or SlideShare presentations.

Lines 18 and 20 of the listing above also show that I have defined two preview views for Windows Live Writer to use.  Windows Live Writer provides a true WYSIWYG experience for blog publishing in that WLW tries to allow you to write your blog post in the same format that your blog is rendered in.  For example, I am at the moment writing my blog post in Windows Live Writer, and Windows Live Writer has rendered the editor with the same column limitations, fonts, etc., that the Sogeti-Phoenix.com blog has.  So while I am editing my blog post, I get to actually see what it's going to look like when published to and rendered on my blog.  We'll cover these templates more in a later post, but I just thought that I'd mention them.

At this point, we have everything that we need for Windows Live Writer to connect to our website, autodetect the publishing service, and determine what features to provide to authors who will be writing content for the website.

I hope that the next post on this subject will be another screencast where we'll take a look at our new website publishing interfaces from the perspective of Windows Live Writer instead of Microsoft Office Word 2007.



Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Related posts

Add comment


 

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Live preview

November 20. 2008 20:46

|