As you may or may not know I’m working on a new version of this blog built on EPiServer Community and EPiServer CMS (the combo also known as Relate+). As EPiServer Community’s admin interface only features a simple text area for authoring blog posts and as I really like Windows Live Writer i decided to create a module for integrating the two.
What it supports
- Posting and editing blog posts with text and images (images is stored in the blog’s Image Gallery)
- Specifying publication date
- Categorization of posts
- Tagging of posts
- Retrieving existing tags from the blog for auto completion
- Custom slugs (URL-segments)
What it doesn’t support
- Adding new categories from Live Writer
- Specifying comments policy
- Specifying author
- Attaching other files than images
Most of these things isn’t supported because I don’t need them and my guess is that, except perhaps being able to add new categories from Live Writer, that is true for most blogs.
The source code
I’ve put together a package including the source code for the module (JoelAbrahamsson.MetaWeblog) and some samples. You’ll have to excuse the JoelAbrahamsson namespace, I did after all create this primarily for my own personal use :)
Using the module
To implement the module for Live Writer integration on your own site you’ll need to do a few things. First of all you need to create a handler (an “.ashx”) that inherits from MetaWeblogHandler in JoelAbrahamsson.MetaWeblog. You must also create a Windows Live Writer manifest which tells Live Writer what the blog supports and doesn’t support. Also, if you want Live Writer to be able to figure out the URL of our handler when someone only enters the URL to your blog you must also implement RSD (Really Simple Discovery).
Creating the handler
When you create the handler you’ll have to supply quite a few parameters to the base class’ (MetaWeblogHandler’s) constructor. Many of these are quite obvious while some will require coding from your part. The declaration for the constructor looks like this:
public MetaWeblogHandler( IBlogHandlerFacade blogHandlerFacade, IDefaultSecurityHandlerFacade securityHandler, ISecurityHandlerFacade securityHandlerFacade, IAuthorHandlerFacade authorHandlerFacade, IImageGalleryHandlerFacade imageGalleryHandlerFacade, IBlogCategoryProvider blogCategoryProvider, ITagHandlerFacade tagHandlerFacade, IBlogTagProvider blogTagProvider, IBlogEntryExcerptProvider blogEntryExcerptProvider, IBlogEntrySlugProvider blogEntrySlugProvider, IBlogProvider blogProvider)
The IBlogHandlerFacade, IDefaultSecurityHandlerFacade, ISecurityHandlerFacade, IAuthorHandlerFacade, IImageGalleryHandlerFacade and ITagHandlerFacade are all part of the EPiAbstractions project and the required assemblies for these are included in the download package. EPiAbstractions contains default implementations for these, so supplying the IBlogHandlerFacade, for instance, is just a matter of supplying an instance of BlogHandlerFacade from EPiAbstractions.Community.Blog.
The other parameters are however a bit trickier as you must supply your own implementations of these interfaces. On the other hand that enables you to customize how the handler works. For instance, the IBlogCategoryProvider supplied in the constructor is what the handler will query when it needs to tell Live Writer which categories are available. For some blogs we might not want to have categories at all, others might want a simple list and some might want a more advanced structure and all of these alternatives are possible to implement by creating our own implementation of IBlogCategoryProvider.
The other interfaces that you’ll have to implement are IBlogTagProvider which supplies a list of existing tags to the handler, IBlogEntryExcerptProvider which helps the handler get and set an excerpt for a post (as that’s not a native property of Blog.Entry), IBlogEntrySlugProvider which the handler uses to set and get a posts slug (which also isn’t a native property of Blog.Entry) and IBlogProvider which the handler uses when it needs to get a list of blogs that a user should be able to post entries is.
The download package’s Samples folder contains two examples with example implementations of these interfaces, one is a very simple implementation that doesn’t support categories, tags excerpts and slugs at all. The other is my implementation for my blog. I suggest you look at both of these but create your own. Please note that neither of these samples are meant to be compiled or used, they are just code samples. With that said, they should work, but neither of the web projects have EPiServer Community “installed”. I’ll probably supply a fully functional sample once my new blog is done.
Adding a Windows Live Writer Manifest
A Windows Live Writer manifest is a XML file named wlwmanifest.xml which you place in your websites root. You can read more about the concept here. Both the sample projects in the download package contains a manifest that matches the handler so you can just copy one of those.
Adding RSD Support
With the above steps done the Live Writer integration is fully functional but only if you give Live Writer the exact URL of the handler. Usually you don’t want to force the users to know the handlers URL though, but only the URL to the blog. To make that work you need to create a RSD XML file and add a meta tag that points to it in the head tag of your websites default page. The meta tag should look something like this:
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://www.myblog.com/Rsd.xml" />
There’s nothing that says that the RSD file actually has to be an XML file, it could just as well be a HTTP handler that returns XML. That way you can have it return different data depending on, for instance, some query string parameter.
A sample Rsd.xml file is included in both sample projects.
References and more reading
- The beginning of something new
- Getting started with EPiServer CMS development
- A toolset for building testable and flexible EPiServer CMS sites
- EPiMVC – A framework for using EPiServer CMS with ASP.NET MVC
- Introducing Truffler – Advanced search made easy
- Custom routing for EPiServer content
- Creating a Custom EPiServer Property with a Custom Class as Value
- Building a search page for an EPiServer 7 site with EPiServer Find