Partager via


XML-RPC with WCF (Updated)

XML-RPC for WCF Download here

I had updated my WCF XML-RPC stack for PDC’08 but never got around to post it (either too busy or too lazy when not busy). The updated source code is attached to this post.

Contrary to the code that I’ve posted a while back, the new XML-RPC implementation is no longer a binding with a special encoder, but is implemented entirely as a set of behaviors and extensions for the WCF Service Model. The behavior will work with WCF 3.5 as it ships in the framework and also with the .NET Service Bus March 2009 CTP.

The resulting Service Model programming experience is completely "normal". That means you can also expose the XML-RPC contracts as SOAP endpoints with all the advanced WCF bindings and features if you like. The behaviors support client and service side. I stripped the config support from this version – I’ll add that back once I get around to it. Here's a snippet from the MetaWeblog contract:

   1: [ServiceContract(Namespace = https://www.xmlrpc.com/metaWeblogApi)]
  2: public interface IMetaWeblog : IBlogger
  3: {
  4:    [OperationContract(Action="metaWeblog.editPost")]
  5:    bool metaweblog_editPost(string postid,
  6:                              string username,
  7:                              string password,
  8:                              Post post,
  9:                              bool publish);
 10: 
 11:    [OperationContract(Action="metaWeblog.getCategories")]
 12:    CategoryInfo[] metaweblog_getCategories( string blogid,
 13:                                             string username,
 14:                                             string password);
 15:     ...
 16: 
 17: }

Setting up the endpoint is very easy. Pick the WebHttpBinding (or the WebHttpRelayBinding for .NET Service Bus), create an endpoint, add the XmlRpcEndpointBehavior to the endpoint and you’re good to go.

   1: Uri baseAddress = new UriBuilder(Uri.UriSchemeHttp, Environment.MachineName, -1, "/blogdemo/").Uri;
  2: 
  3: ServiceHost serviceHost = new ServiceHost(typeof(BloggerAPI));
  4: var epXmlRpc = serviceHost.AddServiceEndpoint(
  5:                   typeof(IBloggerAPI), 
  6:                   new WebHttpBinding(WebHttpSecurityMode.None), 
  7:                   new Uri(baseAddress, "./blogger"));
  8: epXmlRpc.Behaviors.Add(new XmlRpcEndpointBehavior());

The client is just as simple:

   1: Uri blogAddress = new UriBuilder(Uri.UriSchemeHttp, Environment.MachineName, -1, "/blogdemo/blogger").Uri;
  2:             
  3: ChannelFactory<IBloggerAPI> bloggerAPIFactory = 
  4:      new ChannelFactory<IBloggerAPI>(
  5:              new WebHttpBinding(WebHttpSecurityMode.None), 
  6:              new EndpointAddress(blogAddress));
  7: bloggerAPIFactory.Endpoint.Behaviors.Add(new XmlRpcEndpointBehavior());
  8: 
  9: IBloggerAPI bloggerAPI = bloggerAPIFactory.CreateChannel();
 10: 

For your convenience I've included complete Blogger, MetaWeblog, and MovableType API contracts along with the respective data types in the test applications. The test app is a small in-memory blog that you can use with the blogging function of Word 2007 or Windows Live Writer or some other blogging client for testing.

Of the other interesting XML-RPC APIs, the Pingback API has the following contract:

   1:  [ServiceContract(Namespace="https://www.hixie.ch/specs/pingback/pingback")]
  2:  public interface IPingback
  3:  {
  4:      [OperationContract(Action="pingback.ping")]
  5:      string ping(string sourceUri, string targetUri);
  6:  }

and the WeblogUpdates API looks like this:

   1:     [DataContract]
  2:     public struct WeblogUpdatesReply
  3:     {
  4:         [DataMember]
  5:         public bool flerror;
  6:         [DataMember]
  7:         public string message;
  8:     }
  9: 
 10:     [ServiceContract]
 11:     public interface IWeblogUpdates
 12:     {
 13:         [OperationContract(Action = "weblogUpdates.extendedPing")]
 14:         WeblogUpdatesReply ExtendedPing(string weblogName, string weblogUrl, string checkUrl, string rssUrl);
 15:         [OperationContract(Action="weblogUpdates.ping")]
 16:         WeblogUpdatesReply Ping(string weblogName, string weblogUrl);
 17:     }

The code is subject to the Microsoft samples license, which means that you can freely put it into your (blogging) apps as long as you keep the house out of trouble.

Comments

  • Anonymous
    April 04, 2009
    Thank you for submitting this cool story - Trackback from DotNetShoutout

  • Anonymous
    May 26, 2009
    Is this license the same as Microsoft Public License (Ms-PL)?

  • Anonymous
    November 29, 2009
    Thanks for posting this code. This has been very helpful. I did discover a defect in the XmlRpcDataContractSerializationHelper class. When implementing the metaWeblog.newPost operation and using Windows Live Writer to post to the WCF service, the white space in the XML was causing an error in the Deserialize method. In the code that deserializes a struct, at the end of the loop "while (reader.NodeType != XmlNodeType.EndElement)," you need to add the following code:    while (reader.NodeType == XmlNodeType.Whitespace)    {        reader.Skip();    } } // while (reader.NodeType != XmlNodeType.EndElement) If you don't do this, the parsing code is going to fail because it will read a whitespace node instead of an end element and will continue parsing at the end of the struct.