2014-05-10 15 views
12

Desidero utilizzare ReadAsAsync() nel mio progetto mvc con .net 4.0. Il risultato è nullo.Utilizzo di ReadAsAsync <T>() per deserializzare l'oggetto Json complesso

Se entro l'URI per affrontare bar, il risultato in cromo (nomi dei tag sono cambiati):

<ns2:MyListResponse xmlns:ns2="blablabla"> 
    <customerSessionId>xxcustomerSessionIdxx</customerSessionId> 
    <numberOfRecordsRequested>0</numberOfRecordsRequested> 
    <moreResultsAvailable>false</moreResultsAvailable> 
    <MyList size="1" activePropertyCount="1"> 
    <MySummary order="0"> 
     <id>1234</id> 
     <name>...</name> 
     . 
     . 
    </MySummary> 
    </MyList> 
</ns2:MyListResponse> 

Se uso la dichiarazione in codice:

using (var client = new HttpClient()) 
{ 
    var response = client.GetAsync(apiUri).Result; 
    var message = response.Content.ReadAsStringAsync().Result; 

    var result1 = JsonConvert.DeserializeObject<MyListResponse>(message); 
    var result2 = response.Content.ReadAsAsync<MyListResponse>().Result; 
} 

il messaggio viene in formato stringa come "{\"MyListResponse\":{\"customerSessionId\"...}" che corrisponde ad un oggetto jSON come:

{"MyListResponse": 
    {"customerSessionId":"xxcustomerSessionIdxx", 
    "numberOfRecordsRequested":0, 
    "moreResultsAvailable":false, 
    "MyList": 
     {"@size":"1", 
     "@activePropertyCount":"1", 
     "MySummary": 
      {"@order":"0", 
      "id":1234, 
      "name":"...", 
      . 
      . 
      } 
     } 
    } 
} 

e le proprietà di result1 e result2 sono valori null o predefiniti. Le definizioni di classe sono sotto. Voglio leggere il contenuto come un oggetto ma non potrei. Cosa consigli per risolvere questo? Che cosa sto facendo di sbagliato? Grazie in anticipo.

public class MySummary 
{ 
    public int @Order { get; set; } 
    public string Id { get; set; } 
    public string Name { get; set; } 
    . 
    . 
} 

public class MyList 
{ 
    public int @Size { get; set; } 
    public int @ActivePropertyCount { get; set; } 
    public MySummary MySummary{ get; set; } 
} 

public class MyListResponse 
{ 
    public string CustomerSessionId { get; set; } 
    public int NumberOfRecordsRequested { get; set; } 
    public bool MoreResultsAvailable { get; set; } 
    public MyList MyList { get; set; } 
} 

risposta

7

ho definito una nuova classe come:

public class ResponseWrapper 
{ 
    public MyListResponse MyListResponse { get; set; } 
} 

poi ho usato questo involucro con,

var result1 = JsonConvert.DeserializeObject<ResponseWrapper>(message); 
var result2 = response.Content.ReadAsAsync<ResponseWrapper>().Result; 

allora ha funzionato. Ho bisogno solo di MySummary, ma dovrei scrivere più classi per farlo funzionare.

6

Dopo aver letto la soluzione mi è venuta con uno che non ha bisogno di una classe in più:

private static async Task<U> Execute<U>(HttpClient client, string path) 
    { 
     U output = default(U); 

     HttpResponseMessage response = await client.GetAsync(path); 

     if (response.IsSuccessStatusCode) 
     { 
      var jsonAsString = await response.Content.ReadAsStringAsync(); 
      output = JsonConvert.DeserializeObject<U>(jsonAsString); 
     } 
     else 
     { 
      throw new ApplicationException(string.Format("Response message is not OK. Issues in action: {0}", path)); 
     } 

     return output; 
    } 
+1

È possibile semplificare ulteriormente l'output 'output = attende response.Content.ReadAsAync ();' – Nkosi

3

Per motivi di futuri lettori, penso che l'approccio corretto sta usando ReadAsAsync overload che accetta IEnumerable<MediaTypeFormatter> e fornire un formattatore con le stesse impostazioni utilizzate sul server per la serializzazione. Questo dovrebbe risolverlo.

0

È possibile utilizzare direttamente il client ReadAsAsync con MyListResponse (di conseguenza senza ResponseWrapper). Per fare ciò, è possibile definire "BodyStyle = WebMessageBodyStyle.Bare" nel contratto operativo di "apiuri" invece di "BodyStyle = WebMessageBodyStyle.Wrapped" (lato server, cioè contratto di servizio).