Parse REST api response for different possible classes in C#

I'm working with a REST API, that returns 2 different kinds of XML responses for the same request.

For example if I ask for a ticket using some ticket number, say 12345 to this API, it either returns:

  1. The ticket:
  1. Or says that it doesn't have the ticket:

(I couldn't format my XML for some reason so just pasted the screenshot.)

With some help from this JSON2Csharp website, I came up with these classes to represent the response:

The Ticket class:

[XmlRoot(ElementName = "Tickets")]
public class TicketsResponse
{
    public List<Ticket> Tickets { get; set; }
}

[XmlRoot(ElementName = "Ticket")]
public class Ticket
{
    [XmlElement(ElementName = "Field1", IsNullable = true)]
    public string Field1 { get; set; }
    public bool ShouldSerializeField1() { return Field1 != null; }

    [XmlElement(ElementName = "TicketNumber")]
    public int TicketNumber { get; set; }

    [XmlElement(ElementName = "SomeOtherDetails")]
    public SomeOtherDetails SomeOtherDetails { get; set; }

    [XmlElement(ElementName = "Accessorials")]
    public object Accessorials { get; set; }
}

[XmlRoot(ElementName = "SomeOtherDetails")]
public class SomeOtherDetails
{
    [XmlElement(ElementName = "SomeOtherField1", IsNullable = true)]
    public string SomeOtherField1 { get; set; }
    public bool ShouldSerializeSomeOtherField1() { return SomeOtherField1 != null; }
}

The Error class:

[XmlRoot(ElementName = "response")]
public class ErrorResponse
{
    public byte requestId { get; set; }
    public byte errorCode { get; set; }
    public string errorDesc { get; set; }
    public ErrorResponseBody body { get; set; }
}

[XmlRoot(ElementName = "body")]
public class ErrorResponseBody
{
    [XmlElement("errors")]
    public List<Error> errors { get; set; }
}

[XmlRoot(ElementName = "Error")]
public class Error
{
    public byte errorId { get; set; }
    public string errorDescription { get; set; }
    public string errorObjectId { get; set; }
}

I then call the API using a TicketNumber that exists. I'm using RestSharp for calling the api:

public async void SendRequestAndReceiveResponse()
{
    var restClient = new RestClient("https://someapiaddress.net");
    var requestXMLBody = "<request><request_id>1</request_id><operation>retrieve</operation><method /><entity>ticket</entity><user>someuser</user><password>somepassword</password><body><ticket><TicketNumber>12345</TicketNumber></ticket></body></request>";
    var request = new RestRequest("somexmlwebservice!process.action", Method.POST);
    request.AddParameter("xmlRequest", requestXMLBody, "text/xml", ParameterType.QueryString);
    var response = await restClient.ExecuteAsync<TicketsResponse>(request);
    // Do other stuffs with this response...
}

Now this works very well. Because I know my response will have the ticket and that will correctly deserialize to TicketsResponse object.

But if I call the API using a TicketNumber that doesn't exist, I simply get TicketsResponse object that has an empty list of Tickets because this time I'm getting error response. The status code comes to be OK in this case too.

What I want to do here is that I want to capture the error message from the error response. (Response of either Ticket or Error applies to bunch of other processes as well, so it's important to grab this information in a single call.)

And if I knew this ticket doesn't exist, I could simply call the API this way and capture the errors. But that's not ideal nor even a good idea:

var response = await restClient.ExecuteAsync<ErrorResponse>(request);

So I thought of combining TicketsResponse and ErrorResponse, like this:

[XmlRoot]
public class CombinedResponse
{
    [XmlElement(ElementName = "Tickets")]
    public TicketsResponse Data { get; set; }
    [XmlElement(ElementName = "response")]
    public ErrorResponse NonData { get; set; }
}

And get the response using that class:

var response = await restClient.ExecuteAsync<CombinedResponse>(request);

The Status code comes OK (when it returns either data or error message) and I get my correct response in response.Content, but the deserialization doesn't work, so my response.Data will show 2 fields Data and NonData both as null. Ideally I should have gotten either my Ticket data or Error data in response.Data.

So my question is:

Is it possible to make this work using a single class for deserialization?

I have spent too much time on this so any help is appreciated. Also please look at my model classes and suggest if there's better way of doing things.



from Recent Questions - Stack Overflow https://ift.tt/3F3iRSq
https://ift.tt/3nciBuf

Comments

Popular posts from this blog

Spring Elasticsearch Operations

Network Error and Timeout on Authorize.net JS

Object oriented programming concepts (OOPs)