每周源代码55 – NotABlog:一个对 Windows Live Writer说谎的本地 XML-RPC MetaWebLog 端

[原文发表地址]The Weekly Source Code 55 - NotABlog: A Local XML-RPC MetaWebLog Endpoint That Lies To Windows Live Writer

[原文发表时间]2010-08-01 11:15 PM

我的团队有很多东西要写。我们当然会写一些博客帖子,但我们还会为各种各样的网站写许多的教程。https://www.asp.net现在是在Umbraco上运行,而MSDN则运行在内部自定义的系统上,同时还有其他的一些网站。它们唯一的共同点是HTML。

有时有人会用Word来写一篇教程或文档,然后试图从中获得HTML,那只会以痛苦和遭罪而告终。我们可以使用诸如Markdown 或 Dreamweaver 或Expression Web的工具,或者我们自己来编写HTML,但是我们每一次却还是会恢复使用Windows Live Writer。这并不是开玩笑,对于我们的工作流程来说,WLW是我们用到现在最好的博客编辑器。

它创建了干净漂亮的标记语言,并使我们只需要关心最基本的那些标记,对于我们来说也就是H1, P, PRE, UL, LI, ACRONYM, BLOCKQUOTE, IMG 等等,没有太多其他的了。它支持进行编辑和对代码进行着色的插件(我使用的是PreCode plugin),并有着很好的图像处理功能如水印,调整大小及连接到更大的版本,等等。我们很乐意在它里面编辑所有的东西。

问题是,它并不包含一个另存为对话框的选项。 在我们编辑后,我们可以直接选择查看|源代码,并复制这个HTML,但是当我们编辑像$whatever.png这样的名称时,WLW对自定义的类型使用的其实是临时的图像链接,,并把图像隐藏在临时文件及不透明的小块中。

注意: Windows Live Writer确实支持通过Blogger API, MetaWeblog API 和 AtomPub进行编辑及发表。AtomPub是最新的也是最严格的,但是我准备从创建MetaWeblog 服务器开始,因为我对它比较了解而且它简单便捷。我会试着用同样的功能来继续这个帖子,不同的是我马上会用到AtomPub以便可以把二者放在一起讲。请记住MetaWeblog扩展了Blogger API并且全和博客发布及其内容相关。AtomPub不只是关于发布博客,它和编辑一切东西都有关。WLW是一个通过与AtomPub对话的博客客户端,但它并不是广义上的AtomPub客户端。

因此我打算创建的是一个小的本地的"NotABlog"服务器,我可以将Windows Live Writer指向它并使之认为这是一个博客。然后我就能够有效地创建、阅读、及更新那些位于本地发布文件夹的博客帖子(包括HTML文件及与它们相关联的图像)

这个例子对于你及你的机构来说可能会很有意思(或者说是尚未被写出来的AtomPub版本),因为你可能会在你正在工作的现行系统前加上一个端点,并且能够使商业用户使用Windows Live Writer进行编辑内容。WLW对商业人士来说并不是很可怕,它为现有自定义内容管理系统(你可能已经安装了)的更新提供了一个很好的接口。为现有客户端创建一个编辑端点是重振现有内容管理系统的省力办法。

Metaweblog

许多年前(像12年前)XML-RPC由Dave Winer和一些微软员工创建。它不是SOAP,它只是用XML调用HTTP的远程程序。还有其他一些基于XML-RPC创建的协议,它们只是一些接口。它们是有效协议:一个端点将会包含某些带有特定参数的命名的方法。

MetaWeblog API是Dave创建的一个XML-RPC接口,它允许你编辑博客的条目。它是老了点,但却很有效地通用。下面的例子展示了XML-RPC是如何调用的。

<?xml version="1.0"?>

 

<methodCall>

 

  <methodName>examples.getSomething</methodName>

 

  <params>

 

    <param>

 

      <value>

        <i4>70</i4>

      </value>

 

    </param>

 

  </params>

 

</methodCall>

 

Charles Cook创建了一个惊艳而漂亮的图书馆叫做XML-RPC.NET,并把它献给了社区。他使之一直良好地运行,即使在我的第一个版本中我使用的是更老的1.0.0.8版本的.NET 1.0,我还是可以使之在我的.NET 4.0应用程序中运行而不做任何修改。那是对Charles工作的一个证明。之后我下载了2008年最新的版本2.4.0 ,它也运行良好并修复了一些 错误。

2008年, Keyvan Nayyeri用ASP.NET创建了一个漂亮小巧的MetaWeblog ASP 存根。然后我开始用它来进行创建工作。因为是本地编辑,我在ValidateUser方法中只是简单的返回一个true值,。我对Windows Live Writer 撒了谎(在一些地方返回了硬编码的值)。

下面的代码展示了这个接口:

namespace NotABlog

{

    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

    }

}

 

你只需要从Charles的XmlRpcService进行派生,他就会传送HTTP POSTs,调用方法的,及分离参数。( 事实上,回想到开发ASP.NET MVC 1.0的岁月里,出于好奇,Phi 和我编写了XmlRpcRoutes及支持性的示例以验证这是不是可能实现。这确实是可能的。)

这个想法的目的是扑获这些调用并把他们重新定向到文件系统。下面是一个简单的例子;

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

    Post post, bool publish)

{

    if (ValidateUser(username, password))

    {

        string id = string.Empty;

        string postFileName;

        if (String.IsNullOrEmpty(post.title))

            postFileName = Guid.NewGuid() + ".html";

        else

            postFileName = post.title + ".html";

 

        File.WriteAllText(Path.Combine(LocalPublishPath, postFileName), post.description);

        

        return postFileName;

    }

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

}

 

 

如果愿意的话,你可以自己运行一下。如下是怎么来运行。

设置你的本地发布端点
首先,如果你愿意的话,编辑web.config并更改你的本地发布目录。目前,它只是把帖子放到一个.\LocalPublish的文件夹里,这个文件夹在你的Web应用程序的当前目录下。你可以放心的去修改它。我把它放到我的桌面上了。

<?xml version="1.0"?>

<configuration>

  <appSettings>

    <add key="LocalPublishPath" value="C:\LocalPublish"/>

  </appSettings>

  <connectionStrings/>

  <system.web>

    <compilation debug="true" targetFramework="4.0"/>

    <authentication mode="None"/>

  </system.web>

</configuration>

 

因为这是个Web应用程序,我需要一个Web服务器来运行它。我不想用Visual Studio 或 IIS来运行它,因此我决定用WebMatrix里的IIS Express来运行它的,因为这是免费的,而且你并不需要成为管理员就可以运行它(Win2k3除外)。安装了WebMatrix你就会获得IIS Express。

我创建了一个叫做StartNotABlog.bat的批处理文件,并把以下的命令行放了进去:

SET ExecPath=%ProgramFiles(x86)%
IF "%ExecPath%" == "" SET ExecPath = "%ProgramFiles%
"%ExecPath%\Microsoft WebMatrix\iisexpress.exe" /path:"%CD%" /port:12345

这很直接易懂,而且它既可以在x86 上也可以在x64上工作。它以当前目录(是批处理文件正在运行的目录,不是环境的当前目录)作为路径,在12345端口上启动了一个Web服务器。

现在,启动Windows Live Writer。添加一个博客,选择Other…

What kind of Blog Services

并把type选择为"Metaweblog API"。

Choose a Blog Type

输入https://localhost:12345/MetaWeblogAPI.ashx作为远程发布的URL地址。

Enter your remote posting URL

因为并没有设置用户名和密码,所以接下来你可以输入任意内容用来做身份验证。

Windows Live Writer (2)

点击Next 和Finish,然后就可以编辑帖子了。我现在正在使用它来编辑一篇关于ASP.NET的3000字的教程。

clip_image009[16]

Not a Blog.zip. 下载编码并尽情使用。其实它里面并没有太多的东西,但是它已经改变了我工作的方式。现在的诀窍是向老板展示:任意设置一个端点让WLW与之对话是多么容易的事情。或许这个博客帖子会有所帮助。;)