Choose to register. In the API selection list choose ‘MetaWebLog’. In ‘Blog Post URL’ specify the Kentico end-point URL. The default URL looks like ‘http://<your web site>/CMSPages/MetaWeblog.ashx’, same as with WLW.
Click ‘OK’ and proceed to the next step. Complete the setup process. That’s it!
Using Windows Live Writer
In this section, I’d like to mention WLW specific features that are important in the context of cooperation with Kentico CMS, rather than to cover the complete set of WLW features. Most of them are quite intuitive so you’d explore them easily by yourself.
We will use the default Corporate Site for demonstration purposes. Main WLW window would then look something like the following:
- WLW main window
Below, you can find basic description of important parts on the WLW screen. Please note that all the functionality is provided by Kentico CMS integration of MetaWeblogAPI and so it could work in slightly different way when comparing to other blog providers.
As stated on the image above:
Publishing blog post
Publish – moves your post to Kentico CMS,
New – creates new post ready for editing,
Open – lets you select from an existing posts related to the current blog,
Save draft – when workflow is applied for the current blog, new minor version is created after posting a draft,
Edit post area – if WLW detected the blog theme correctly, you can see style applied to the area. You can see that in case of Corporate Site feel and look matches the current blog style,
Insert menu – allows you to insert media objects of different types (image, map, video, etc.),
View mode selection – switching the mode you can check how the blog will look like after the post goes live,
Category selector – displays tags available for the current blog,
Publish date selector – capability to postpone publishing the post. Even when the post is transferred to Kentico CMS, its publish date is set accordingly. Thus the post is not going live until the date and time is met.
Let’s assume you are creating a new blog post. You specify post title and enter body text. Include some image, link, map or YouTube video. All of those objects can be simply added through the insert menu – all effects are predefined thus no further manipulation is required. Your blog post could then look like the one below:
- Blog post example
The current version of WLW (and MetaWeblogProviderAPI) is missing a support for blog post summary text. If you are familiar with Kentico CMS document types, you probably know that each blog post document contains the ‘Post summary’ field. It’s intended to keep the summary text related to the particular blog post. In our integration with MetaWeblogAPI we provide you with the ‘Allow automatic summary’ setting. When you navigate to ‘Site manager-> Settings-> Meta Weblog API’ you can decide whether the beginning of the post body should be automatically populated for the ‘Post summary’ field. Number of characters copied is specified by ‘Site manager-> Settings-> Meta Weblog API-> Summary length’ setting.
Now you are ready to publish the post to your blog. Going to ‘Preview’ view mode, you may preview the blog before you actually publish the post to make sure it meets your expectations. In case of emergency you can even modify the output HTML code directly using the ‘Source’ view mode. If you do not modify the publish date of the post and just hit the ‘Publish’ button the post is transferred over to Kentico CMS and displayed under the current blog immediately.
However, you can set a specific publish date through the publish date selector. Although you use the same ‘Publish’ button, the post doesn’t shows up on the blog page yet. It is caused by the fact that selected date and time value is used for the ‘Post date’ and the ‘Publish from’ fields of the blog post document. The post doesn’t get published until the specified time as Kentico CMS document engine takes care of this for you.
If your blog has a workflow scope applied, you can use ‘Save draft’ in addition to the options mentioned earlier. Using ‘Save draft’ allows you to store draft locally or on-line. Publishing blog post on-line as the draft causes new minor version of the blog post node to be created. Once you feel like going live with your draft, use ‘Publish’ to create a new major version and therefore move your post live. Please note that whenever full-page caching is enabled for the blog page, your recently published
post might not be visible until the cache is invalid and restored with actual data.
Multimedia objects in post
Almost every blog post you write involves some kind of media. Whether it is an image or photo album object, WLW makes it heaven for you to work with. Once you publish your post to Kentico CMS, each multimedia object becomes a new attachment of the document representing your blog post in the system. We have introduced the concept of document attachments in version 4.1.
Attachments of the particular post could be managed manually through ‘CMSDesk-> Content-> Edit-> <blog post node>-> Properties-> Attachments
’ or automatically using the ‘Delete unused attachments
’ from ‘Site manager-> Settings-> MetaWeblog API
’ settings section. This option allows you to let the system remove unused attachments from the blog posts. Attachment is considered unused when no reference to it is found within the post text.
- Blog post attachments
Managing blog posts
If you don’t need to perform complex managing tasks, you can take advantage of the built-in administration capabilities. Using the ‘Open’ action button in the toolbar at the top of the screen the dialog is opened. As you can see in the image below, you can review recent posts or open posts of a particular blog. At the top you can see the ‘Delete’ button used to delete the selected blog post. Please note that deleting a blog post removes all versions of the specified post and cannot be restored later.
- Blog posts management
Tags in Windows Live Writer
MetaWeblog API natively supports categories to be specified for a blog post. Even though Kentico CMS features category management as well, I’ve decided to use tags in place of categories. It is mostly because we believe tags are commonly used by bloggers, while categories aren’t used as much as tags and tag clouds concerning blogs. If you take a look at the bottom part of WLW screen, you notice the category selector. In our case better said ‘Tag selector’, though. It basically displays all the tags falling into the tag group assigned for the current blog. You can choose multiple tags from the list if you wish. When you use Community Server as your default blog type, you might even add new tags using the ‘Add Category’ text box displayed on the right.
- Blog post tags in WLW
If you publish the post, you can check it through ‘CMSDesk-> Content-> Edit-> <blog post node>-> Properties-> Metadata-> Tags’
- Blog post tags in CMS Desk
Microsoft Word: If you decide to use MS Word as your blogging tool, exactly the same set of tag options as you get with WLW is available for you. You can select either from existing tags or create a new one directly from within the MS Word environment.
Multilingual and multisite support
If you already got in touch with Kentico CMS, you probably evaluated its multilingual support as well. Kentico CMS basically creates a new record for each language version of a particular document. With blog documents it is the same. For example, let’s assume you have the blog ‘My blog’ in English version and the same blog in German version with the name ‘Mein blog’. If you configure your WLW’s blog account, you will be given an option to select either the ‘My blog (en-US)’ or ‘Mein blog (de-DE)’ blog. In this way, you’re in fact able to select what language version you want to manage. Please be aware of fact that WLW doesn’t pass any information on currently selected language version of your blog to the browser client. Thus, the recently viewed version of the blog page is displayed. Therefore, please make sure you have proper culture version selected on your page to review the last inserted post of some particular language version.
As long as you use a single instance of Kentico CMS to manage multiple web sites, you may also manage blogs of those web sites through the same MetaWeblog API ASHX handler. It means that all blogs coming from all sites from within the single CMS instance are accessible through the WLW.
Webfarm, Import & Export and Staging support
All document operations are performed on the server side. As you will see in the upcoming tech part of this text, standard methods for inserting, updating and publishing documents in Kentico CMS are used. It is no surprise then that integration with WLW natively supports webfarm environment, import and export procedures and staging functionality.
What is MetaWeblog API?
The MetaWeblog API is a programming interface that allows external blogging tools to create, edit and delete blog entries on particular blog server. The interface uses popular XML-RPC communication protocol for transmitting blog post related information along with blog user details. If you are into RFC specifications, you could find one for MetaWeblog API at http://www.xmlrpc.com/metaWeblogApi
MetaWeblog API extends older Blogger API. Blogger API includes only basic functionality. It lacks support for uploading files. Whenever you decide to use media files in your Blogger-based blog post, you could either implement some custom provider if your blogging tool allows it or in most cases do it manually. MetaWeblog API introduced enriched set of supported procedures that could be eventually used to enclose media files to your blog post.
We’ll discuss all the procedures in the next section.
What is XML-RPC?
XML-RPC is a standardized communication protocol using HTTP for transport and XML for encoding. It is used to perform remote procedure calls over the Internet. As architecture independent technology, it allows to invoke procedures on systems running different OS. XML-RPC was intended to be as simple as possible while allow transmitting complex data structures. Due to this fact, MetaWeblog API is able to transfer images, video and other media files over the internet in form of simple objects that are deserialized, transmitted and serialized again. You can learn more about XML-RPC project at http://www.xml-rpc.net/
Communication between WLW and Kentico CMS - MetaWeblog API
MetaWeblog API consists of several procedures that are called during the WLW runtime based on the action you’re currently performing. I’ve created a list of those procedures. You can find it in the table following upon last paragraph of this section (figure 11). I’ve also included equivalents for each of the procedures that are used by Kentico’s MetaWeblogAPI ASHX handler to handle the requested actions.
When you open WLW and click ‘Open’, the request for blogger.getUsersBlogs procedure to get all blogs user signup for. As soon as you select particular blog, call for metaWeblog.getRecentPosts is made. All posts related to the selected blog are displayed. Double-click on specific post and metaWeblog.getPost procedure is invoked. Blog entry is opened and displayed to you. You now change the text a bit, add some media files and fine-tune post layout. Then you hit the ‘Publish’ button and metaWeblog.editPost procedure is called. In case you create new post metaWeblog.newPost is raised instead. Later when you decide to remove post from the blog, you hit the ‘Delete’ button in the ‘Open’ dialog and procedure blogger.deletePost is asked to serve your request. Blog post is successfully removed and single communication cycle is over.
Whenever your text contains a media file, call to metaWeblog.newMediaObject is made prior to the metaWeblog.editPost/metaWeblog.newPost procedure. It ensures that the file is uploaded to the server successfully and retrieved URL pointing to the file is placed at the actual position of the file in the text.
List of MetaWeblog API procedures and matching methods from MetaWeblogAPI class implemented by Kentico.
- List of MetaWeblog API methods
MetaWeblogAPI provider library
Probably the most interesting part of MetaWeblog API integration with Kentico CMS comes in form of the MetaWeblogProvider library.
The library contains several files briefly described subsequently:
Structures to discuss
IMetaWeblogAPI.cs – interface defining required API methods as well as transformation rules for translating XML-RPC procedure calls to actual .NET methods,
MetaWeblogAPIObjects.cs – contains all the structures used to handle blog related information (BlogInfo, CategoryInfo, Post, etc.) as well as user specific details,
MetaWeblogAPI.cs – master class providing all the blog service functionality using methods from Kentico CMS API to ensure correct functionality.
I’m not going to talk about all structures used by MetaWeblog API as most of them are self-explaining. Instead, I would like to go through two of them.
The structure looks like:
public struct Post
public DateTime dateCreated;
public string description;
public string title;
public string categories;
public string permalink;
public object postid;
public string userid;
public string wp_slug;
When publishing the blog post using MetaWeblogAPI compliant blogging software, the procedure called receives information on post as the Post structure. Among others, you can see the description that contains the text of the post, categories handling information on tags post is assigned with; permalink is used for storing the permanent link to the blog post document.
The structure looks like:
/// Media object structure (image, video, audio, etc.)
public struct MediaObject
public string name;
public string type;
public byte bits;
The name attribute contains a unique name given by WLW to the media file. The MIME type of the media file is specified by type value. Binary data are held by the bits array.
In the final part of this text, I’m going to explain how Kentico CMS API is used to perform the requested operations. I’m going to talk about a pair of methods that in my opinion merit your attention the most.
MetaWeblogAPI.AddPost / MetaWeblogAPI.UpdatePost
When you create a new post or edit an existing one, either AddPost() or UpdatePost() method is called when blog entry is pushed to the blog server to be stored within the Kentico CMS.
public string AddPost(string blogid, string username, string password,
MetaWeblogAPIObjects.Post post, bool publish)
public bool UpdatePost(string postid, string username, string password,
MetaWeblogAPIObjects.Post post, bool publish)
As with almost every MetaWeblogAPI method, the user is authenticated and verified for the blog at first place. It helps to prevent unwanted modifications to the blogs not allowed for the user.
With Kentico CMS, each blog post is located under the document representing the month of post publish date. It helps users to organize their blogs. To comply with this approach, the AddPost()
method ensures that the related blog month document exists before the post is saved. Blog month is based on the value coming from the post.dateCreated attribute. The value, however, reflects user’s local time while the server time is required. Transformation to the server time zone is performed by the method below:
private DateTime GetBlogPostPublishDate(DateTime postCreated)
// Get publish date and convert it into server time zone
DateTime publishDate = (postCreated != DateTime.MinValue)? postCreated : DateTime.Now;
return TimeZoneHelper.ConvertServerDateTime(publishDate, this.User);
All blog post related information is available through the post parameter.
When an existing document is edited, the UpdatePost() method causes check-out before changes are made to the post. However, check-out is only performed for workflowized blogs when ‘Site manager-> Settings-> Content management-> Use check in/ check out’ is turned-on. I would like to emphasize that whenever you are manipulating with the existing document, you should perform check-out before and check-in after the job is done. This way, you not only gain an exclusive access to the document but also assure the correct document flow as well. Need to mention that VersionManager.CheckOut() method causes the document to switch to edit workflow step automatically. Therefore, new minor version of the post is created with every check-out.
Blog post document is eventually created using the DocumentHelper.InsertDocument() method. If you edit an existing blog post, DocumentHelper.UpdateDocument() is called to update the post document. Please note the DocumentHelper is used as we need to make sure that the full set of workflow-related sub-actions gets executed in case the blog uses workflow.
Once the post is created/ updated, we need to make sure that the appropriate workflow step is set when relevant. Review the method below to see how the document’s current workflow step could be moved with Kentico CMS API:
private void BlogPostPublishHandler(bool publish, TreeNode postNode)
// Get the workflow manager and info on document's current step if document uses workflow
if (publish && (this.WorkflowManager.GetNodeWorkflow(postNode) != null))
// Get current step info
WorkflowStepInfo currentStep = this.WorkflowManager.GetStepInfo(postNode);
// Approve until the step is PUBLISH
while ((currentStep != null) && (currentStep.StepName.ToLower() != "published"))
if (currentStep.StepName.ToLower() == "archived")
currentStep = this.WorkflowManager.MoveToPreviousStep(postNode, string.Empty);
currentStep = this.WorkflowManager.MoveToNextStep(postNode, string.Empty);
// Release any version information on post when workflow isn't used any more
If the blog post node is subject to the workflow, the WorkflowManager.GetNodeWorkflow() method returns a WorkflowInfo object. If no workflow applies for the current blog, no further processing is required; only old workflow information is removed by DocumentHelper.ClearWorkflowInformation().
In the implementation of the publish handler above, you can see the way how the blog post is published based on the publish parameter. The document actually passes over all the workflow steps until the publish step is met.
Before the post is saved and processed by the publish handler, all uploaded files that are part of the post need to be stored as post document attachments. While I get to definition of this method, I should explain how the media objects are actually transmitted to the server. All the media objects are sent to the server one-by-one prior to the post publishing. On the server-side, the MetaWeblogAPI.NewMediaObject() takes over the files and stores them as temporary attachments. Temporary attachments reside in storage in form of groups marked by specified unique identifier. This functionality is supported natively by Kentico CMS. It comes in really handy especially in case when you need to store attachments before the related document is created. When you are ready to move attachments to the target location, you simply access them through the identifier and specify their destination. Kentico CMS takes care about the rest for you.
In MetaWeblog API implementation, each blog gets its own unique guid identifier assigned. Blog guids are stored within the blogGuid collection, where guid is value and blog’s NodeID key. All the temporary attachments related to the specific blog are persisted under the particular blog’s guid. Next time the blog post is created, the guid is obtained from the blogGuid collection and temporary attachments are assigned to the recently created/updated blog post node.
Temporary attachments are stored as shown by the sample code from MetaWeblogAPI.NewMediaObject()
// Get media object name
string mediaObjName = Path.GetFileName(mediaObject.name);
// Get attachment manager
AttachmentManager am = new AttachmentManager(this.TreeProvider.Connection);
// Create new attachment for file document
AttachmentInfo ai = new AttachmentInfo(this.TreeProvider.Connection);
ai.AttachmentBinary = mediaObject.bits;
ai.AttachmentExtension = Path.GetExtension(mediaObjName);
ai.AttachmentGUID = Guid.NewGuid();
// Get image dimensions if applicable
ImageHelper ih = new ImageHelper(ai.AttachmentBinary);
if (ih != null)
ai.AttachmentImageHeight = ih.ImageHeight;
ai.AttachmentImageWidth = ih.ImageWidth;
ai.AttachmentLastModified = TimeZoneHelper.ConvertServerDateTime(DateTime.Now, this.User);
ai.AttachmentMimeType = mediaObject.type;
ai.AttachmentName = mediaObjName;
ai.AttachmentSiteID = this.BlogNode.NodeSiteID;
ai.AttachmentSize = mediaObject.bits.Length;
// Save new attachment as temporary attachment
if (blogGuid[this.BlogNode.NodeID] == null)
blogGuid[this.BlogNode.NodeID] = Guid.NewGuid();
am.AddTemporaryAttachment((Guid)blogGuid[this.BlogNode.NodeID], null, Guid.Empty, Guid.Empty, ai, this.BlogNode.NodeSiteID, 0, 0, 0);
// Fill in information on newly uplaoded file and return it as required
mediaObj.url = UrlHelper.ResolveUrl(DocumentHelper.GetAttachmentUrl(ai, 0));
Now, I can get back to the point where we were talking about creating/updating blog posts and storing temporary attachments for the current post. This part of job is performed by the MetaWeblogAPI.PublishAttachments()
method as shown at the sample below:
private void PublishAttachments(TreeNode postNode, bool deleteExisting)
DataSet ds = DocumentHelper.GetAttachments(postNode, null, null, false, this.TreeProvider);
// Get list of attachment guids from post text (both summary as well as body)
ArrayList attGuids = GetAttachmentsGuid(postNode);
bool listEmpty = (attGuids == null);
foreach (DataRow dr in ds.Tables.Rows)
Guid attGuid = ValidationHelper.GetGuid(dr["AttachmentGUID"], Guid.Empty);
// Skip the attachment when still being used by the post
if (!listEmpty && attGuids.Contains(attGuid))
// Delete unused attachment
DocumentHelper.DeleteAttachment(postNode, attGuid, this.TreeProvider);
if ((blogGuid[this.BlogNode.NodeID] != null) && (postNode != null))
DocumentHelper.SaveTemporaryAttachments(postNode, (Guid)blogGuid[this.BlogNode.NodeID], this.SiteName, this.TreeProvider);
Based on the ‘Site manager-> Settings-> MetaWeblog API-> Delete unused attachments
’ setting, you can force the system to delete all unused attachments before post publishing takes place. We decided to equip our MetaWeblog implementation with such support because sometimes you may want to automatically remove attachments that aren’t used any more. In the current implementation of MetaWeblog API with Kentico CMS, it is done by searching for references to existing attachments and eliminating all attachments not referred, thought. The method simply goes through all attachments that belong to the current post, checks if references exist in the post text and deletes unused attachments eventually.
Hopefully, you find this post useful. We like blogging with Windows Live Writer in such a way that we decided to built-in MetaWeblog API support within the upcoming version of Kentico CMS. Please let me know if you have any ideas on how to improve the current version of MetaWeblog API integration with Kentico CMS
. If you may feel like you're missing something there, use comments below to share your thoughts.
Also, as this is my first integration report I would be very happy if you help me improve it. If you're looking for some specific type of information that is obviously missing, please suggest as well.