Implement MetaWeblog API in ASP.NET

There is no doubt that MetaWeblog API is one of the very helpful and popular inventions around online publishing especially for blog engines and services. Of course MetaWeblog API has not been a tool only for blogs because it's used as a general publishing service for other sites as well.

During the time, MetaWeblog API is extended by some famous blogging engines and services like Blogger and WordPress to add some common features to it but the core features are what many users are looking for.

There are several plus points for MetaWeblog API that has made it a great choice for online publishing including the ease of editing, capability of having a local copy and many other features. Some great tools like Windows Live Writer or BlogJet are working based on these APIs.

MetaWeblog API is simply built on top of XML-RPC API which acts based on XML communications between a client and a server. This API consists of some structures for common objects in blogging (like blog, user, post, category or media objects) as well as some methods to add, edit, get or delete them.

There are many implementations for MetaWeblog API in different technologies including .NET (ASP.NET) but I couldn't find any good resource that helps much for .NET implementation. The first time that I was going to implement this API for a site, after some researches I finally ended up with discovering an open source implementation code.

So I'm going to write this post to describe how to implement MetaWeblog API in .NET in the simplest form that I can.

Concepts

As I stated above, MetaWeblog API is an API based on XML-RPC communications. It means that you have a set of pre-defined structures (with simple data types as properties) that are being transferred between client and server. There are also some methods that apply these structures.

There are six structures that you need to use in the MetaWeblog API:

As a general rule, you can keep in mind that MetaWeblog API uses string type as the basic type for many properties, parameters and return types and there isn't any integer type. Boolean and base64 encoded string are two other types in a few places.

There are also nine methods to use in the MetaWeblog API:

These structures and methods have a pre-defined structures with special data types and you must keep their structures in your code because they're a standard structure and all the tools and clients are built to work with them.

This is the main part of MetaWeblog API (not its core and original implementation) but I wrote that some famous blogging engines and services like Blogger or WordPress have added a few features to this core functionality with new structures that have become common among users. For example, Blogger has three helpful methods including blogger.deletePost, blogger.getUserInfo and blogger.getUsersBlogs.

Here I ignore WordPress addition but cover Blogger methods because they're very common. The usage and implementation of other methods is very similar to the core features.

How to Implement MetaWeblog API in .NET

The process of implementing MetaWeblog API for your .NET applications is straightforward and consists of a few steps that I'll describe. But before talking about these steps, there is an obvious requirement for the implementation and that is a library to work with XML-RPC in .NET. You most likely know the most common and famous one, XML-RPC.NET, that is serving in many .NET applications. You just need to add a reference to this assembly in your projects.

But how about the implementation? The implementation consists of four steps in general:

I describe each step in the next sections.

Create an HTTP Handler

The first and simplest step is to create a webservice or HTTP Handler to act as the entry point for the API. Below code is enough to do this for me and move the rest to my MetaWeblog class implementation.

<%@ WebHandler Language="C#" CodeBehind="MetaWeblogAPI.ashx.cs" Class="MetaWeblogSample.MetaWeblogAPI" %>

Build the Structures

Now you need to build the abovementioned structures of MetaWeblog API in your code. I don't step in details about the structures since they're constant structures that you can understand from MetaWeblog API specification.

The below code is all I need to build my structures. You usually can simply use same code in your applications because these are constant structures.

using System;

using System.Data;

using System.Configuration;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

using CookComputing.XmlRpc;

 

namespace MetaWeblogSample

{

    #region Structs

 

    public struct BlogInfo

    {

        public string blogid;

        public string url;

        public string blogName;

    }

 

    public struct Category

    {

        public string categoryId;

        public string categoryName;

    }

 

    [Serializable]

    public struct CategoryInfo

    {

        public string description;

        public string htmlUrl;

        public string rssUrl;

        public string title;

        public string categoryid;

    }

 

    [XmlRpcMissingMapping(MappingAction.Ignore)]

    public struct Enclosure

    {

        public int length;

        public string type;

        public string url;

    }

 

    [XmlRpcMissingMapping(MappingAction.Ignore)]

    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;

    }

 

 

    [XmlRpcMissingMapping(MappingAction.Ignore)]

    public struct Source

    {

        public string name;

        public string url;

    }

 

    public struct UserInfo

    {

        public string userid;

        public string firstname;

        public string lastname;

        public string nickname;

        public string email;

        public string url;

    }

 

    [XmlRpcMissingMapping(MappingAction.Ignore)]

    public struct MediaObject

    {

        public string name;

        public string type;

        public byte[] bits;

    }

 

    [Serializable]

    public struct MediaObjectInfo

    {

        public string url;

    }

 

    #endregion

}

Define the Interface

The next step is to build an interface for MetaWeblog API based on the structures that you have defined. You need to mark your methods with an XmlRpcMethod attribute (included in XML-RPC.NET library) that gets the service method name as its parameter. Again, this interface is obvious from the MetaWeblog specification. There are two groups of methods for core MetaWeblog API and Blogger API.

using System;

using System.Data;

using System.Configuration;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

using CookComputing.XmlRpc;

 

namespace MetaWeblogSample

{

    public interface IMetaWeblog

    {

        #region MetaWeblog API

 

        [XmlRpcMethod("metaWeblog.newPost")]

        string AddPost(string blogid, string username, string password, Post post, bool publish);

 

        [XmlRpcMethod("metaWeblog.editPost")]

        bool UpdatePost(string postid, string username, string password, Post post, bool publish);

 

        [XmlRpcMethod("metaWeblog.getPost")]

        Post GetPost(string postid, string username, string password);

 

        [XmlRpcMethod("metaWeblog.getCategories")]

        CategoryInfo[] GetCategories(string blogid, string username, string password);

 

        [XmlRpcMethod("metaWeblog.getRecentPosts")]

        Post[] GetRecentPosts(string blogid, string username, string password, int numberOfPosts);

 

        [XmlRpcMethod("metaWeblog.newMediaObject")]

        MediaObjectInfo NewMediaObject(string blogid, string username, string password,

            MediaObject mediaObject);

 

        #endregion

 

        #region Blogger API

 

        [XmlRpcMethod("blogger.deletePost")]

        [return: XmlRpcReturnValue(Description = "Returns true.")]

        bool DeletePost(string key, string postid, string username, string password, bool publish);

 

        [XmlRpcMethod("blogger.getUsersBlogs")]

        BlogInfo[] GetUsersBlogs(string key, string username, string password);

 

        [XmlRpcMethod("blogger.getUserInfo")]

        UserInfo GetUserInfo(string key, string username, string password);

 

        #endregion

    }

}

Implement the Interface

And the last step is to implement your MetaWeblog API interface (IMetaWeblog in my example) as well as XmlRpcService from XML-RPC.NET library which simply turns your class to an XML-RPC service.

You need a logic to validate users based on their username and password and then let them do something in the methods. Here things vary based on your local implementation of blog engine or site so I just left code comments for the implementation part.

using System;

using System.Data;

using System.Configuration;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

using CookComputing.XmlRpc;

using System.Collections.Generic;

 

namespace MetaWeblogSample

{

    public class MetaWeblog : XmlRpcService, IMetaWeblog

    {

        #region Public Constructors

 

        public MetaWeblog()

        {

        }

 

        #endregion

 

        #region IMetaWeblog Members

 

        string IMetaWeblog.AddPost(string blogid, string username, string password,

            Post post, bool publish)

        {

            if (ValidateUser(username, password))

            {

                string id = string.Empty;

 

                // TODO: Implement your own logic to add the post and set the id

 

                return id;

            }

            throw new XmlRpcFaultException(0, "User is not valid!");

        }

 

        bool IMetaWeblog.UpdatePost(string postid, string username, string password,

            Post post, bool publish)

        {

            if (ValidateUser(username, password))

            {

                bool result = false;

 

                // TODO: Implement your own logic to add the post and set the result

 

                return result;

            }

            throw new XmlRpcFaultException(0, "User is not valid!");

        }

 

        Post IMetaWeblog.GetPost(string postid, string username, string password)

        {

            if (ValidateUser(username, password))

            {

                Post post = new Post();

 

                // TODO: Implement your own logic to update the post and set the post

 

                return post;

            }

            throw new XmlRpcFaultException(0, "User is not valid!");

        }

 

        CategoryInfo[] IMetaWeblog.GetCategories(string blogid, string username, string password)

        {

            if (ValidateUser(username, password))

            {

                List<CategoryInfo> categoryInfos = new List<CategoryInfo>();

 

                // TODO: Implement your own logic to get category info and set the categoryInfos

 

                return categoryInfos.ToArray();

            }

            throw new XmlRpcFaultException(0, "User is not valid!");

        }

 

        Post[] IMetaWeblog.GetRecentPosts(string blogid, string username, string password,

            int numberOfPosts)

        {

            if (ValidateUser(username, password))

            {

                List<Post> posts = new List<Post>();

 

                // TODO: Implement your own logic to get posts and set the posts

 

                return posts.ToArray();

            }

            throw new XmlRpcFaultException(0, "User is not valid!");

        }

 

        MediaObjectInfo IMetaWeblog.NewMediaObject(string blogid, string username, string password,

            MediaObject mediaObject)

        {

            if (ValidateUser(username, password))

            {

                MediaObjectInfo objectInfo = new MediaObjectInfo();

 

                // TODO: Implement your own logic to add media object and set the objectInfo

 

                return objectInfo;

            }

            throw new XmlRpcFaultException(0, "User is not valid!");

        }

 

        bool IMetaWeblog.DeletePost(string key, string postid, string username, string password, bool publish)

        {

            if (ValidateUser(username, password))

            {

                bool result = false;

 

                // TODO: Implement your own logic to delete the post and set the result

 

                return result;

            }

            throw new XmlRpcFaultException(0, "User is not valid!");

        }

 

        BlogInfo[] IMetaWeblog.GetUsersBlogs(string key, string username, string password)

        {

            if (ValidateUser(username, password))

            {

                List<BlogInfo> infoList = new List<BlogInfo>();

 

                // TODO: Implement your own logic to get blog info objects and set the infoList

 

                return infoList.ToArray();

            }

            throw new XmlRpcFaultException(0, "User is not valid!");

        }

 

        UserInfo IMetaWeblog.GetUserInfo(string key, string username, string password)

        {

            if (ValidateUser(username, password))

            {

                UserInfo info = new UserInfo();

 

                // TODO: Implement your own logic to get user info objects and set the info

 

                return info;

            }

            throw new XmlRpcFaultException(0, "User is not valid!");

        }

 

        #endregion

 

        #region Private Methods

 

        private bool ValidateUser(string username, string password)

        {

            bool result = false;

 

            // TODO: Implement the logic to validate the user

 

            return result;

        }

 

        #endregion

    }

}

Wrapping Up

At this point you're able to test the service simply by navigating to the URL of your HTTP Handler.

MetaWeblog API

There are some extra implementations and features similar to this main implementation that you can inspire for your code. MetaWeblog API and its extended features are a great way to simplify the process of content publishing on your site and are easy to implement. I hope that more developers try to use it in their works. I can remember that three years ago I recommended this API to the founder and developer of the most famous and popular Persian blogging service but he never attended to my recommendation and it (along some other stuff) has kept his engine an amateur blogging engine (from a technical point of view).

You can download the source code sample of this post from here.

[advertisement] Axosoft OnTime 2008 is four developer tools in one: bug tracking, project wiki, feature management, and help desk. It manages your development process so developers can focus on coding. Installed or Hosted – Free Single-user license -- Free 30-day team trial.

16 Comments : 05.10.08

Feedbacks

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Pingback from Dew Drop - May 10, 2008 | Alvin Ashcraft's Morning Dew

 avatar
#3
µilad
05.10.2008 @ 3:17 PM

Thanks for the gr8 and helpful post keyvan! For a long time I wanted to implement this, but I couldn't make it because of time problems!

BTW thanks again ;)

Pingback from Reflective Perspective - Chris Alcock » The Morning Brew #91

Pingback from Wöchentliche Rundablage: ASP.NET MVC, Silverlight 2, TDD, WPF, jQuery… | Code-Inside Blog

Pingback from Weekly Links: ASP.NET MVC, Silverlight 2, TDD, WPF, jQuery… | Code-Inside Blog International

Pingback from A cool article that shows how to implement MetaWebLog API in .NET « Scott Tucker’s Weblog

Back in May I wrote a blog post as a guide to implement MetaWeblog API in ASP.NET . There are some common

One of my yesterday’s blog posts was about implementing a trackback handler in ASP.NET and I stated that

Pingback from MetaWeblog, Trackback and Pingback in ASP.NET « vincenthome’s Software Development

 avatar
#11
Barry H.
10.24.2008 @ 7:02 AM

Great article! Thanks for sharing.

 avatar
#12
Sprogz
11.12.2008 @ 10:25 AM

Really helpful. Thank you.

 avatar
#13
Christian Groß
11.22.2008 @ 3:05 PM

Great work!

Monthly Top 10 Favorite useful Articles

 avatar
#15
Silverlight Travel
12.13.2008 @ 1:02 PM

Great idea. I us it now by myselfe.

 avatar
#16
My Best Blog Posts in 2008
12.31.2008 @ 1:40 PM

In the past 3.5 years of blogging, I haven’t had such best pick up collections in the end of the year, but now that everybody is writing one, why shouldn’t I write my own?! Collecting this list, I could realize some interesting facts that completely changed

Leave a Comment