MetaWeblog API in .NET

Published on May 05, 2008

MetaWeblog API in .NET

    MetaWeblog , I tell you, is a rather interesting little thing. Simple and clear aki doors. When you understand everything there.

    About Protocols


    I first came across this interface at the moment when I screwed an API to my wiki engine to edit these same wiki pages and blog posts. The Blogger API was n’t suitable because the guys from Google, who were developing the GData API based on the Atom Publishing Protocol , turned their backs on it, and the APP itself was not yet standardized. There was no intelligible documentation for the Movable Type API, but there were no others.

    About Russian programmers


    Be that as it may, I settled on the MetaWeblog API. Since it was built on top of XML-RPC , there was a need for a library that would take all these low-level details onto itself. One was found: XML-RPC.NET (author - Charles Cook ). A good library, in general, but not without cons. Firstly, it’s too heavyweight - you get code generation, Remoting support, the ability to create your own stand-alone XML-RPC server, and much more. Thirdly, the documentation is not so hot there. And finally, when serializing structures, only public fields were taken into account, which maybe not so bad, but it didn’t suit me.

    In short, it was decided to write his own library (oh yes, “ they didn’t write it"Is also an important factor). The result is available on Google Code .

    octalforty brushie web


    That's what I called it, yes.

    The most important class is XmlRpcService; abstract and realizing widely known System.Web.IHttpHandler. To create your own XML-RPC service, it’s enough to inherit from this class and mark the exposed methods with the attribute XmlRpcServiceMethodAttribute: For primitive types (which is) this is enough. If you need to transfer structures (I use the word “structure” with reference to XML-RPC, and not .NET), then the class (here we are talking about .NET) should be additionally marked: That's all. Nothing more is needed to know about XML-RPC.
    public class MathXmlRpcService : octalforty.Brushie.Web.XmlRpc.XmlRpcService
    {
      [XmlRpcServiceMethod("add")]
      public int Add(int x, int y)
      {
        return x + y;
      }
    }

    int
    [XmlRpcStructure()]
    public class BlogPostCategory
    {
      private string title = String.Empty;

      [XmlRpcMember("title")]
      public string Title
      {
        get { return title; }
        set { title = value; }
      }
    }



    MetaWeblog API


    Now is the turn to implement the API itself. Having octalforty.Brushie.Web.XmlRpc.XmlRpcServiceall the associated infrastructure in hand , the only thing left is to understand a rather vague specification and write the appropriate code. With Fiddler in one hand and Windows Live Writer in the other, I began my research. As a result, such a stone flower came out .

    Now the implementation of the API has become obscenely simple: inherit the service class from XmlRpcServiceyes to implement IMetaWeblogService.

    Toward the close ...


    ... an example of how the implementation looks NewMediaObject.
    namespace octalforty.Kudos.Web.Api.Wiki
    {
      ///   /// A MetaWeblog XML-RPC service for editing wiki pages.
      ///
      public class MetaWeblogService : XmlRpcService, IMetaWeblogService, IPageManagerServiceDependency,
        ISpaceManagerServiceDependency, INavigationServiceDependency,
        IGlobalTagManagerServiceDependency, ISecurityServiceDependency,
        IUserManagerServiceDependency, IPageAttachmentManagerServiceDependency
      {
        public MediaObjectInfo NewMediaObject(string blogID, string login, string password, MediaObject mediaObject)
        {
          if(!SecurityService.IsValid(login, password))
            throw new SecurityException();

          //
          // Parsing media object name.
          if(mediaObject.Name.IndexOf("^") < 0)
            throw new ArgumentException();

          string pageName = mediaObject.Name.Substring(0, mediaObject.Name.IndexOf("^"));
          string attachmentName = mediaObject.Name.Substring(mediaObject.Name.IndexOf("^") + 1);

          Space space = SpaceManagerService.GetSpaceByID(Convert.ToInt64(blogID));
          Page page = PageManagerService.GetPageBySpaceKeyAndPageName(space.Key, pageName);

          PageAttachment pageAttachment = PageAttachmentManagerService.GetPageAttachmentByName(page, attachmentName);
          if(pageAttachment == null)
          {
            pageAttachment = new PageAttachment(attachmentName, mediaObject.MimeType);
            page.AddAttachment(pageAttachment);
          } // if

          pageAttachment.AddRevision(new PageAttachmentRevision(UserManagerService.GetUserByLogin(login), mediaObject.Content));

          PageManagerService.SavePage(page);

          return new MediaObjectInfo(NavigationService.ResolveVirtualUrl(NavigationService.GetPageAttachmentUrl(pageAttachment)));
        }
      }
    }