2015-04-23 22 views
5

Abbiamo uno scenario in cui l'API esterna restituisce XML utente o XML di errore in base al fatto che la richiesta abbia esito positivo o negativo.È possibile passare 2 tipi di oggetti a Restsharp?

Al momento sto passando User POCO al restsharp e funziona correttamente. Ma se fallisce, questo oggetto è NULL. E non sapremo perché è fallito a meno che non analizziamo manualmente l'XML di errore.

C'è un modo per aggirare questo?

ad es.

var restClient = new RestClient(baseURL); 
var request = new RestRequest(uri); 
request.Method = Method.POST; 
var response = restClient.Execute<User>(request); 

In esecuzione del metodo precedente l'API può restituire l'oggetto xml Errore. Come ottengo l'errore dell'oggetto in caso di errore e l'utente in caso di successo?

+0

Potrebbe includere il codice che non funziona? – svick

+0

Si prega di vedere l'aggiornamento –

+1

Penso che se può restituire l'errore XML o XML utente, quindi non restituisce 'Utente'. Cattiva progettazione da parte degli sviluppatori di server per restituire due formati XML distinti. Esiste una forma di "Esegui" che restituisce XML? Quindi è possibile esaminare l'XML per vedere quale formato è e deserializzare in oggetti 'User' o' Error'. –

risposta

4

Questo è possibile, sebbene il codice sia un po 'brutto. RestSharp ti permette di specificare il tuo deserializzatore XML, quindi dovremo farlo per farlo funzionare.

Prima, però, è necessario un tipo di dati che consente di memorizzare un Error o un User (ho fatta generico in modo che funziona per più appena Utenti):

public class Result<T> 
{ 
    public T Data { get; set; } 
    public Error Error { get; set; } 
} 

Così l'idea è, ora quando si esegue la richiesta, si chiede RestSharp per un Result<User> invece di un User, vale a dire:

Ora ecco la magia necessaria per deserializzare sia come Error o un User. È un deserializzatore personalizzato che eredita da XmlDeserializer di RestSharp. Attenzione: questo codice non è stato testato, ma si spera che possa indicarti la giusta direzione.

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; 
    } 
} 

Poi si dovrebbe legare il tutto così:

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... 
} 
Problemi correlati