We have scenario where external API returns either User XML or Error XML based on whether request succeed or failed.
At the moment I'm passing User POCO to the restsharp and works fine. But if it fails, this object is NULL. And we won't know why it failed unless we parse the Error XML manually.
Is there a way to workaround this?
e.g.
var restClient = new RestClient(baseURL);
var request = new RestRequest(uri);
request.Method = Method.POST;
var response = restClient.Execute<User>(request);
On execution of above method the API can return Error xml object. How do I get Error object on fail and User on success?
This is possible, although the code is a little ugly. RestSharp allows you to specify your own XML deserializer, so we'll need to do that in order to make this work.
First, though, you need a data type that can store either an Error
or a User
(I made it generic so it works for more than just Users):
public class Result<T>
{
public T Data { get; set; }
public Error Error { get; set; }
}
So the idea is, now when you execute the request, you ask RestSharp for a Result<User>
instead of just a User
, i.e.:
var result = client.Execute<Result<User>>(request);
Now here's the magic required to deserialize as either an Error
or a User
. It's a custom deserializer that inherits from RestSharp's XmlDeserializer
. Warning: this code is not tested at all, but it can hopefully point you in the right direction.
public class XmlResultDeserializer : XmlDeserializer
{
public override T Deserialize<T>(IRestResponse response)
{
if (!typeof(T).IsGenericType || typeof(T).GetGenericTypeDefinition() != typeof(Result<>))
return base.Deserialize<T>(response);
// Determine whether the response contains an error or normal data.
var doc = XDocument.Parse(response.Content);
var result = Activator.CreateInstance<T>();
if (doc.Root != null && doc.Root.Name == "Error")
{
// It's an error
var error = base.Deserialize<Error>(response);
var errorProperty = result.GetType().GetProperty("Error");
errorProperty.SetValue(result, error);
}
else
{
// It's just normal data
var innerType = typeof(T).GetGenericArguments()[0];
var deserializeMethod = typeof(XmlDeserializer)
.GetMethod("Deserialize", new[] { typeof(IRestResponse) })
.MakeGenericMethod(innerType);
var data = deserializeMethod.Invoke(this, new object[] { response });
var dataProperty = result.GetType().GetProperty("Data");
dataProperty.SetValue(result, data);
}
return result;
}
}
Then you would wire it all up like this:
var restClient = new RestClient(baseURL);
client.AddHandler("application/xml", new XmlResultDeserializer());
var request = new RestRequest(uri);
request.Method = Method.POST;
var result = restClient.Execute<Result<User>>(request);
if (response.Data.Data != null)
{
var user = response.Data.Data;
// Do something with the user...
}
else if (response.Data.Error != null)
{
var error = response.Data.Error;
// Handle error...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With