How to deserialize XML if the return type could be an Error or Success object
I am working with an XML based API that as its root node can either return a SuccessResponse
or a ErrorResponse
.
I am using the below to deserialize the data but I am not sure how to handle the case of the return not being a SuccessResponse
.
What is the best way to handle the situation where the returned XML isn't in the expected format?
I know I could do a hack way and look for the occurrance of either SuccessResponse
or ErrorResponse
but that doesn't feel right.
TheIconicApiResult result = this.apiService.SendGetRequest("GetProducts", new List<AbstractParam>() { new FilterParam("live"), new LimitParam(5000) });
IXmlSerialiser xmlSerialiser = new XmlSerialiser();
var xmlBody = xmlSerialiser.ParseXML<SuccessResponse>(result.ResponseBody);
public TObject ParseXML<TObject>(string xml)
{
using (TextReader reader = new StreamReader(GetMemoryStream(xml)))
{
XmlSerializer serialiser = new XmlSerializer(typeof(TObject));
return (TObject)serialiser.Deserialize(reader);
}
}
In situations where you have an XML stream containing one of several possible document types, you can construct an XmlSerializer
for each type and call XmlSerializer.CanDeserialize(XmlReader)
to successively test whether the document can be deserialized into that type. This method does not advance the XmlReader
past the root element so it can be called multiple times without re-reading the stream.
For instance, you could introduce the following extension method:
public static partial class XmlSerializerExtensions
{
public static object DeserializePolymorphicXml(this string xml, params Type[] types)
{
using (var textReader = new StringReader(xml))
{
return textReader.DeserializePolymorphicXml(types);
}
}
public static object DeserializePolymorphicXml(this TextReader textReader, params Type[] types)
{
if (textReader == null || types == null)
throw new ArgumentNullException();
var settings = new XmlReaderSettings { CloseInput = false }; // Let caller close the input.
using (var xmlReader = XmlReader.Create(textReader, settings))
{
foreach (var type in types)
{
var serializer = new XmlSerializer(type);
if (serializer.CanDeserialize(xmlReader))
return serializer.Deserialize(xmlReader);
}
}
throw new XmlException("Invalid root type.");
}
}
Then use it as follows:
var xmlBody = result.ResponseBody.DeserializePolymorphicXml(typeof(SuccessResponse), typeof(FailResponse));
if (xmlBody is SuccessResponse)
{
// Handle successful response
}
else if (xmlBody is FailResponse)
{
// Handle failed response
}
else
{
// unknown response
throw new InvalidOperationException("unknown response");
}
Sample fiddle.