JDSolutions :: smart software

XML-RPC Library
for .NET

Jon Davis <jon@jondavis.net>
JD Solutions


[ Download v2.1.1 ]


Changelog:

Version 2.1.1Fixed a bug for invalid empty nodes - 6/20/2004
Version 2.1Added auto-redirection ability for XmlRpcClient - 3/27/2004
Version 2.0.1Fixed the client so that requests are made in UTF-8 rather than ASCII - 1/14/2004
Version 2.0A number of bug fixes and enhancements have been made, including limited asynchronous support and a bug fix with the Content-Length before posting to server - 1/2/2004
Version 1.5.1 - Major improvements (fix for empty arrays; added to BloggerProxy: structs and methods for blogger, MetaWeblog, MoveableType APIs) - 3/2/2003
Version 1.5 - Major improvements (added BloggerProxy.asmx SOAP/XML-RPC bridge (for testing); added XmlRpcStructClrMember class, added XmlRpcStruct.ToClrMembersArray() method; fixed empty string value parsing) - 3/1/2003
Version 1.4.1 - Major improvements (added service introspection [untested]) - 2/7/2003
Version 1.4 - Major improvements (in XmlRpcClient: made ProxySettings, Cookies public; added Certificates, Headers, UserAgent, Encoding; added SharedXmlDocument to XmlRpcTools for consolidated .NET framework based on-the-fly XML/text encodings via node creation; allow for hiding documentation in methods) - 2/7/2003
Version 1.3 - Major improvements (improved XmlRpcTools.SerializeObject(), added XmlRpcTools.DeserializeObject()) - 2/6/2003
Version 1.2.5 - Minor improvements (improved XmlRpcStruct constructor handling of hashtable full of non-IXmlRpcElement types) - 2/4/2003
Version 1.2.4 - Design changes (support for "XmlRpcException(msg, code, this)" to manage method exceptions) - 2/4/2003
Version 1.2.3 - Minor improvements (improved XmlRpcTools.SerializeObject()) - 2/4/2003
Version 1.2.2 - Design changes (renamed XmlRpcTools.StructureObject() to SerializeObject()) - 2/4/2003
Version 1.2.1 - Design changes (added XmlRpcBoolean constructors, Hashtable property for XmlRpcStruct) - 2/4/2003
Version 1.2 - Design change (XmlRpcStruct[indexer] returns [value] rather than [member] object) - 2/4/2003
Version 1.1.4 - Critical bug fix (attribute-named method invocation) - 2/3/2003
Version 1.1.3 - Critical bug fix (typecasting) - 2/3/2003
Version 1.1.2 - Critical bug fix (typecasting) - 2/3/2003
Version 1.1.1 - Critical bug fix (web interface) - 2/3/2003
Version 1.1 - Critical bug fix (web interface) - 2/3/2003


What Is XML-RPC?

XML-RPC is an XML web services specification similar to SOAP, but much simpler in implementation. Only eight data types are supported: int, double, base64, boolean, datetime.iso8601, string, array, and struct. For more information, visit http://www.xml-rpc.com

This XML-RPC Library for .NET is a programming framework for the .NET framework (or other CLR implementations, such as possibly Mono) that extends ASP.NET for building and deploying applications that utilize the XML-RPC specification.


 
Namespaces

IXmlRpcElements, such as XmlRpcInteger, XmlRpcString, etc., are exposed in the JDSolutions.XmlRpc.Elements namespace. All other objects are exposed in the JDSolutions.XmlRpc namespace.

Example:

using JDSolutions.XmlRpc;
using JDSolutions.XmlRpc.Elements;



Instructions

To use the client, create an XmlRpcClient object and call its Call method.

Example:

  XmlRpcClient xrc = new XmlRpcClient();
  int i = ((int)xrc.Call("www.jondavis.net", "/JDSolutions/XmlRpcTest/", 
    "MyTestService.Add", new Object[] {2, 3}));
  Response.Write(i.ToString());
  Response.End(); 

To use the server, inherit XmlRpcService and pass the HTTP context to ProcessRequest(). XmlRpcService implements IHttpHandler and IRequiresSessionState, so ASP.NET can process an XmlRpcService object as an HttpHandler.

Optionally, label your service class with the attribute: [XmlRpcServiceAttribute("[NAME OF SERVICE]")].

Finally, you must label the methods of your service class with the attribute:

 [XmlRpcMethod("[Method Name]"]

or:

 [XmlRpcMethod("[Method Name]", 
   Description = "[Method description]",
   InfoUrl = "[URL to more information about this method]",
   HideDocumentation = false)] 

Example:

[XmlRpcServiceAttribute("My Test Service")]
public class TestService : XmlRpcService {
	
	[XmlRpcMethod("TestService.Add", 
		 Description = "This is a test", 
		 InfoUrl = "http://www.jondavis.net/",
		 HideDocumentation = false)]
	public int Add(int i1, int i2) {
		return i1+i2;
	}
	[XmlRpcMethod("TestService.DemoStruct")]
	public XmlRpcStruct DemoStruct() {
		Hashtable s = new Hashtable();
		s.Add("name1", null);
		s.Add("name2", null);
		s["name1"] = "val1";
		s["name2"] = "val2";
		return new XmlRpcStruct(s);
	}

	[XmlRpcMethod("TestService.CustomStruct")]
	public structobject CustomStruct() {
		return new structobject();
	}
}

For a live demonstration with source code, visit: http://www.jondavis.net/JDSolutions/XmlRpcTest


 
Types

All values that are exchanged between the HTTP client and the HTTP service are stored in IXmlRpcElement objects. For instance, a <string></string> node value would be stored in an XmlRpcString, which is one of several IXmlRpcElement object types.

All IXmlRpcElement objects have a method called ToXml(), which serializes the object for XML-RPC.

The XML-RPC Library for .NET attempts to automatically convert IXmlRpcElement objects back to CLR objects, such as from XmlRpcString to System.String, wherever possible. However, sometimes explicit use of IXmlRpcElements objects is required, particularly with the use of structs and arrays. In these cases, as when extracting a struct member value from an XmlRpcStruct object, the type of that value will be an IXmlRpcElement type, not a CLR type.

Example:

  Hashtable ht = new Hashtable(); // create a hashtable
  ht.Add("name1", "value1"); // add a value
  ht.Add("name2", "value2");

   // create an XmlRpcStruct object from the hashtable
  XmlRpcStruct myStruct = new XmlRpcStruct(ht);

   // returns an XmlRpcString, not a String
  XmlRpcString myXString1 = (XmlRpcString)myStruct["name1"];

   // String must be extracted from XmlRpcString
  String myString1 = myXString1.Value;

The following XML-RPC to CLR type map is applied:

int, i4 -> XmlRpcInteger -> System.Int32
double -> XmlRpcDouble -> System.Double
base64 -> XmlRpcBase64 -> System.Byte[]
boolean -> XmlRpcBoolean -> System.Boolean
datetime.iso8601 -> XmlRpcDateTime -> System.DateTime
string -> XmlRpcString -> System.String
array -> XmlRpcArrayList -> System.Collections.ArrayList
array <- XmlRpcArrayList <- [OTHER CLASS OF ARRAY TYPE]
struct -> XmlRpcStruct -> System.Collections.DictionaryBase / System.Collections.Hashtable
struct <- XmlRpcStruct <- [OTHER CLASS WITH FIELDS OR PROPERTIES]
member -> XmlRpcStructMember -> System.Collections.DictionaryEntry

CLR to IXmlRpcElement typecast examples:

XmlRpcInteger i = new XmlRpcInteger((int)object);
XmlRpcInteger i = new XmlRpcInteger(3);
XmlRpcString s = new XmlRpcString((string)object);
XmlRpcString s = new XmlRpcString("stringvalue");
XmlRpcDateTime dt = new XmlRpcDateTime((DateTime)object);
XmlRpcDateTime dt = new XmlRpcDateTime((string)iso8601_string);
XmlRpcDateTime dt = new XmlRpcDateTime("20020204T12:27:35");
XmlRpcBoolean b = new XmlRpcBoolean((Boolean)object);
XmlRpcBoolean b = new XmlRpcBoolean(true);
XmlRpcBoolean b = new XmlRpcBoolean(1);
XmlRpcBoolean b = new XmlRpcBoolean("true");
XmlRpcBoolean b = new XmlRpcBoolean("1");
XmlRpcBase64 bt = new XmlRpcBase64((Byte[])object);
XmlRpcBase64 bt = new XmlRpcBase64((String)base64_data);
XmlRpcDouble d = new XmlRpcDouble((Double)object);
XmlRpcDouble d = new XmlRpcDouble(1.5);
XmlRpcArrayList AL = new XmlRpcArrayList((System.Array)object);
XmlRpcArrayList AL = new XmlRpcArrayList((ArrayList)object);
XmlRpcArrayList AL = new XmlRpcArrayList();
  AL.Add((XmlRpcString)object);
XmlRpcStruct ST = new XmlRpcStruct((Hashtable)object);
XmlRpcStruct ST = new XmlRpcStruct();
  ST.Add("name1", (XmlRpcString)value1_object);

IXmlRpcElement to CLR typecast examples:

int i = ((XmlRpcInteger)object).Value;
string s = ((XmlRpcString)object).Value;
DateTime dt = ((XmlRpcDateTime)object).Value;
bool b = ((XmlRpcBoolean)object).Value;
byte[] bt = ((XmlRpcBase64)object).Value;
double d = ((XmlRpcDouble)object).Value;
ArrayList AL = ((XmlRpcArrayList)object).Value;
IDictionary D = ((XmlRpcStruct)object).Value;
Hashtable H = ((XmlRpcStruct)object).Hashtable;

The XmlRpcStruct type is based on DictionaryBase but operates more like a Hashtable. It has an indexer that returns the value associated with the specified key. That value will always be an IXmlRpcElement type.

Example:

string s = ((XmlRpcString)myStruct["myValue"]).Value;

Conversions and Serialization:

You can also perform object type conversions by using XmlRpcTools.ConvertElement().

Example:

string s = (string)XmlRpcTools.ConvertElement(myXmlRpcString, false);
XmlRpcString s = (XmlRpcString)XmlRpcTools.ConvertElement("my string", true);

If you have other objects, such as custom objects that contain fields and properties, ConvertElement() will call SerializeObject(), which will produce an XmlRpcStruct object from it, up to two object field levels deep.

Example:

public class myClass
{
    public string fName = "fValue";
}
   
...
    myClass myclass = new myClass();
    XmlRpcStruct ST = (XmlRpcStruct)XmlRpcTools.ConvertElement(myclass, true);
    // which is the same as...
    XmlRpcStruct ST2 = XmlRpcTools.SerializeObject(myclass);

ST/ST2 above would be an XmlRpcStruct class which contains the name/value item(s) of the converted object, myclass. In this case, the one name/value pair it contains is an XmlRpcString object containing "fValue", with a key of "fName".

    string returned_fName = ((XmlRpcString)ST["fName"]).Value;

You can also convert an XmlRpcStruct into a custom type of choice, if your custom type is provided, by using DeserializeObject().

MyCustomType myObject = new MyCustomType();
myObject.MyVal1 = "value1";
myObject.MyStruct2 = new XmlRpcStruct();
myObject.MyStruct2.Add("struct2_name1", "struct2_value1");

// serialize
XmlRpcStruct mySerializedObject = XmlTools.SerializeObject(myObject);
// sample output
string XmlOfMyObject = mySerializedObject.ToXml();

 // deserialize
 MyCustomType myObject2 = (MyCustomType)XmlTools.DeserializeObject(
      mySerializedObject, typeof(MyCustomType));
// sample output
string myVal1 = myObject2.MyVal1

Errors and Exceptions:

To throw an exception and send it back to the client, use the following procedure:

   throw new XmlRpcException(myErrorCode, myDescription, this);

Remember to use 'this'. It's used in passing the exception to the service processor so that the client can receive the exception message.



Donate

If you use the XML-RPC Library for .NET, please send a PayPal donation. [DONATE]


Copyright © 2003 JD Solutions. All Rights Reserved. jon@jondavis.net