April 3, 2009
@ 05:09 PM

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 = http://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="http://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.

Monday, May 18, 2009 12:36:20 PM UTC
Hi,

When calling the ping service on weblogs.com I get an error...

End element 'value' from namespace '' expected. Found text 'Thanks'. Line 1, position 109.

I've investigated further - and the value is "Thanks for the ping".

The error occurs when trying to deserialize the response - struct/Member/Value . In the case of weblogs.com, the value is not wrapped in a type. My understanding is that this should still deserialize, but default to a string. Is there a change available for this, or will I need to dive in and make the changes myself?

Also, the reader only seems to bring back the work Thanks, and stop at the space. Again - just delving into this now and would appreciate a pointer in the right direction.

Thanks

PK
Comments are closed.