MetaWeblog, скажу я вам, — довольно занятная вещица. Простая и ясная аки двери. Когда всё там поймешь.
Впервые я столкнулся с этим интерфейсом в тот момент, когда прикручивал к своему вики-движку API для редактирования этих самых вики-страниц и постов в блоги. Blogger API не подошел из-за того, что ребята из Google, занятые разработкой GData API, основанного на Atom Publishing Protocol, от него отвернулись, а сам APP еще не был стандартизирован. По Movable Type API не нашлось внятной документации, а других как-то и не нашлось.
Как бы то ни было, остановился я на MetaWeblog API. Поскольку построен он поверх XML-RPC, возникла потребность в библиотеке, которая брала бы все эти низкоуровневые детали на себя. Таковая нашлась: XML-RPC.NET (автор — Charles Cook). Неплохая, в общем-то, библиотека, но не без минусов. Во-первых, слишком тяжеловесная — там тебе и кодогенерация, и поддержка Remoting, и возможность создать свой stand-alone XML-RPC сервер, и еще много чего. В-третьих, с документацией там не ахти. И, наконец, при сериализации структур в расчет брались только общедоступные поля, что, может быть, не так уж и плохо, но мне не подходило.
Короче говоря, решено было написать свою библиотеку (ах да, «его писали не они» — тоже немаловажный фактор). Результат доступен на Google Code.
Вот так и назвал, да.
Самый главный класс — это
Для примитивных типов (коим
Вот в общем-то и всё. Больше ничего о XML-RPC знать не требуется.
Настал черед реализации самого API. Имея в руках
Теперь реализация API стала делом до неприличия простым: унаследовать класс сервиса от
… пример того, как выглядит реализация
О протоколах
Впервые я столкнулся с этим интерфейсом в тот момент, когда прикручивал к своему вики-движку API для редактирования этих самых вики-страниц и постов в блоги. Blogger API не подошел из-за того, что ребята из Google, занятые разработкой GData API, основанного на Atom Publishing Protocol, от него отвернулись, а сам APP еще не был стандартизирован. По Movable Type API не нашлось внятной документации, а других как-то и не нашлось.
О русских программистах
Как бы то ни было, остановился я на MetaWeblog API. Поскольку построен он поверх XML-RPC, возникла потребность в библиотеке, которая брала бы все эти низкоуровневые детали на себя. Таковая нашлась: XML-RPC.NET (автор — Charles Cook). Неплохая, в общем-то, библиотека, но не без минусов. Во-первых, слишком тяжеловесная — там тебе и кодогенерация, и поддержка Remoting, и возможность создать свой stand-alone XML-RPC сервер, и еще много чего. В-третьих, с документацией там не ахти. И, наконец, при сериализации структур в расчет брались только общедоступные поля, что, может быть, не так уж и плохо, но мне не подходило.
Короче говоря, решено было написать свою библиотеку (ах да, «его писали не они» — тоже немаловажный фактор). Результат доступен на Google Code.
octalforty Brushie Web
Вот так и назвал, да.
Самый главный класс — это
XmlRpcService
; абстрактный и реализующий широко известный System.Web.IHttpHandler
. Для создания собственного XML-RPC-сервиса достаточно унаследоваться от этого класса и пометить выставляемые наружу методы атрибутом XmlRpcServiceMethodAttribute
:public class MathXmlRpcService : octalforty.Brushie.Web.XmlRpc.XmlRpcService
{
[XmlRpcServiceMethod("add")]
public int Add(int x, int y)
{
return x + y;
}
}
Для примитивных типов (коим
int
и является) этого достаточно. Если же потребуется передавать структуры (слово «структура» я употребляю применительно к XML-RPC, а не к .NET), то класс (вот здесь речь уже о .NET) надо дополнительно разметить:[XmlRpcStructure()]
public class BlogPostCategory
{
private string title = String.Empty;
[XmlRpcMember("title")]
public string Title
{
get { return title; }
set { title = value; }
}
}
Вот в общем-то и всё. Больше ничего о XML-RPC знать не требуется.
MetaWeblog API
Настал черед реализации самого API. Имея в руках
octalforty.Brushie.Web.XmlRpc.XmlRpcService
и всю сопутствующую инфраструктуру, дело остается за малым — понять довольно расплывчатую спецификацию и написать соответствующий код. Взяв в одну руку Fiddler, а в другую — Windows Live Writer я начал исследование. В результате вышел вот такой каменный цветок.Теперь реализация API стала делом до неприличия простым: унаследовать класс сервиса от
XmlRpcService
да реализовать IMetaWeblogService
.Под занавес...
… пример того, как выглядит реализация
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)));
}
}
}