Reputation: 6348
I am trying to work with a couple of different XML-RPC API services provided by a third party. I am using the xml-rpc.net library from Cook Computing: http://xml-rpc.net/
I need help mapping Array response types from an XML-RPC API implementation to strongly typed C# objects.
There are 2 different implementations of the xml-rpc spec that are being used, one for each. One is using a fairly easy to work with implementation, using StructParams with a nice logical structure.
The other one... not so much.
I have managed to get the requests across reliably, the problem comes with the responses. There are 3 different response types:
This response is not too difficult to work with, it contains a struct with a nested struct and an int, which can be mapped to something like:
public class Response
{
public Result[] Result;
public int Status;
}
public struct Result
{
public string Status;
}
The XML in the response which can map as above is:
<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>Result</name>
<value>
<array>
<data>
<value>
<struct>
<member>
<name>Status</name>
<value>Everything is OK</value>
</member>
</struct>
</value>
</data>
</array>
</value>
</member>
<member>
<name>TransactionID</name>
<value><i4>123</i4></value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>
This one gives me a slight problem, but I have been able to overcome it with some nasty extension methods, which I'm not happy with. It's similar to above, but the Result is now an array of an array of values, which I can only visualize as object[][][], so I am mapping it to:
public struct Response
{
public object[][][] Result;
}
From this, I can then use my extension method which uses reflection to map the individual objects in the final array to a specific struct with the correct types.
I'm hoping someone can think of a nicer way of doing this. Here's the response XML that I am trying to map:
<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>Result</name>
<value>
<array>
<data>
<value>
<array>
<data>
<value><i4>1</i4></value>
<value>second slot (string)</value>
<value><double>1.23</double></value>
<value><i4>1</i4></value>
<value>Another string slot</value>
</data>
</array>
</value>
</data>
</array>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>
Array responses are where it becomes really tricky. I've not been able to get anything to work reliably with these kinds of responses.
I have tried adding an extra dimension to the object array as with the struct response, but then I'm left with object[][][][]
which I would then have to grab the final 2 dimensions, loop through them and map them to an array of a specific struct. I'm REALLY hoping there's an alternative method that I'm missing here.
Here's the sample XML for this kind of response:
<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>Result</name>
<value>
<array>
<data>
<value>
<array>
<data>
<value>
<array>
<data>
<value>
<i4>1</i4>
</value>
<value>Disk Space</value>
<value>MB</value>
<value>
<i4>200</i4>
</value>
<value>
<double>0.000000</double>
</value>
<value>
<i4>0</i4>
</value>
</data>
</array>
</value>
<value>
<array>
<data>
<value>
<i4>2</i4>
</value>
<value>Traffic</value>
<value>GB</value>
<value>
<i4>20</i4>
</value>
<value>
<double>1.000000</double>
</value>
<value>
<i4>0</i4>
</value>
</data>
</array>
</value>
</data>
</array>
</value>
</data>
</array>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>
Any pointers on how to map these kinds of responses simply and correctly would be appreciated.
Thanks, James.
Upvotes: 2
Views: 5778
Reputation: 1999
XML-RPC.NET doesn't currently support mapping arrays onto a class or struct type, though there is nothing in principal to prevent this (i.e. you could annotate the class/struct members with their order in the array using a new version of the XmlRpcMember attribute and modify the serializer/deserializer). But for now you have to do something similar to what you suggested, though I think you got the array dimensions wrong and the types should be defined like this:
public class StatusResponse
{
public Result[] Result;
public int TransactionID;
}
public struct Result
{
public string Status;
}
public struct StructureResponse
{
public object[][] Result;
}
public struct ArrayResponse
{
public object[][][] Result;
}
Upvotes: 3