
Jon
Davis <jon@jondavis.net>
JD Solutions
[ Download v2.1.1 ]
Version
2.1.1 - Fixed a bug
for invalid empty nodes - 6/20/2004
Version
2.1 - Added
auto-redirection ability for XmlRpcClient - 3/27/2004
Version 2.0.1 - Fixed
the client so that requests are made in UTF-8 rather than ASCII - 1/14/2004
Version
2.0 - A 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
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.
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;
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
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.
If you use the XML-RPC Library for .NET, please send a PayPal donation. [DONATE]