Reputation: 138
One of our requirements is to have a decoupled architecture where we need to map data from one system to another, and the intermediate mapping is handled by a ServiceStack service request. Our issue is that a vendor can only provide data via Xml that does not conform to the standard dictionary request that ServiceStack offers like below:
<Lead xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d2p1:KeyValueOfstringstring>
<d2p1:Key>String</d2p1:Key>
<d2p1:Value>String</d2p1:Value>
</d2p1:KeyValueOfstringstring>
</Lead>
Instead they need a mechanism like:
<Lead>
<LeadId>Value</LeadId>
<FirstName>First Name</FirstName>
<LastName>Last Name</LastName>
...
</Lead>
Since the nodes in their xml request may change over time, and we're simply acting as a middle-man, is there a native way to accept a dynamic request or handle this as Dictionary with data similar to what's below?
Dictionary<string, string>
{
{ "LeadId", "Value" },
{ "FirstName", "First Name" },
{ "LastName", "Last Name" }
...
};
Upvotes: 2
Views: 227
Reputation: 143319
The default XML Serialization doesn't provide any way that you could transparently infer an XML fragment into a string dictionary so you're going to need to manually parse the XML which you can do in ServieStack by telling ServiceStack to skip built-in Serialization by implementing IRequiresRequestStream
which ServiceStack will inject with the Request Stream so you can deserialize it yourself, e.g:
public class Lead : IRequiresRequestStream
{
public Stream RequestStream { get; set; }
}
In your Service you'd then manually parse the raw XML and convert it to the data collections you want, e.g:
public class RawServices : Service
{
public object Any(Lead request)
{
var xml = request.RequestStream.ReadFully().FromUtf8Bytes();
var map = new Dictionary<string, string>();
var rootEl = (XElement)XDocument.Parse(xml).FirstNode;
foreach (var node in rootEl.Nodes())
{
var el = node as XElement;
if (el == null) continue;
map[el.Name.LocalName] = el.Value;
}
return new LeadResponse {
Results = map
}
}
}
Upvotes: 2