2012-12-17 1 views
13

J'utilise HttpClient de .NET pour envoyer des requêtes à un WebAPI qui renvoie des données JSON qui nécessitent un peu de désérialisation personnalisée côté client. Pour cela j'ai fait mon propre JsonConverter, mais je ne peux pas comprendre comment faire pour que la méthode ReadAsAsync<T> prenne en compte l'existence du convertisseur..net HttpClient avec JsonConverter personnalisé

J'ai résolu mon problème pour l'instant en utilisant ReadAsStringAsync pour lire la réponse, puis en passant cette chaîne à JsonConvert.DeserializeObject, mais il semble qu'il devrait y avoir une solution plus élégante.

Voici mon code:

public PrefsResponse GetAllPrefs(string sid) { 
    HttpClient client = CreateHttpClient(null, sid); 
    var response = client.GetAsync("api/sites/" + sid).Result; 

    // TODO : find a way to hook custom converters to this... 
    // return response.Content.ReadAsAsync<PrefsResponse>().Result; 

    var stringResult = response.Content.ReadAsStringAsync().Result; 

    return JsonConvert.DeserializeObject<PrefsResponse>(stringResult, new PrefClassJsonConverter()); 
} 

Est-ce le meilleur que je peux faire, ou est-il une façon plus élégante?

Voici où je crée le HttpClient aussi, si c'est là où je dois le brancher:

 private HttpClient CreateHttpClient(CommandContext ctx, string sid) { 
     var cookies = new CookieContainer(); 

     var handler = new HttpClientHandler { 
      CookieContainer = cookies, 
      UseCookies = true, 
      UseDefaultCredentials = false 
     }; 

     // Add identity cookies: 
     if (ctx != null && !ctx.UserExecuting.IsAnonymous) { 
      string userName = String.Format("{0} ({1})", ctx.RequestingUser.UserName, ctx.UserExecuting.Key); 
      cookies.Add(new Cookie(__userIdCookieName, userName)); 
      cookies.Add(new Cookie(__sidCookieName, sid)); 
      cookies.Add(new Cookie(__hashCookieName, 
            GenerateHash(userName, Prefs.Instance.UrlPrefs.SharedSecret))); 
     } 

     var client = new HttpClient(handler) { 
      BaseAddress = _prefServerBaseUrl 
     }; 

     client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 



     return client; 
    } 

Répondre

13

Vous pouvez passer la JsonSerializerSettings avec la liste de vos convertisseurs au JsonMediaTypeFormatter qui sera utilisé par ReadAsAsync<T>:

-à-dire

var obj = await result.Content.ReadAsAsync<refsResponse>(
    new[] {new JsonMediaTypeFormatter { 
      SerializerSettings = new JsonSerializerSettings { 
       Converters = new List<JsonConverter> { 
       //list of your converters 
       } 
      } 
      } 
    }); 
+1

Je n'avais aucune idée JSON.Net avait sa propre notion de convertisseurs! Alors maintenant, nous avons trois choses qui peuvent faire le même travail. Classes HttpContent dérivées, MediaTypeFormatters dérivés et JsonConverter dérivé .... –

+0

C'est ce que je cherchais. En fin de compte, je vais avec ce que j'avais à l'origine, car je dois également mettre en cache la réponse sur le disque en cas de basculement sur des demandes futures. –

+0

Merveilleux! J'avais besoin de personnaliser d'autres paramètres JSON.NET et c'était la pièce manquante du puzzle pour moi :) –

1

Peut être que vous souhaitez utiliser HttpClient.GetStringAsync Method (String)

var response = client.GetStringAsync("api/sites/" + sid); 
return JsonConvert.DeserializeObject<PrefsResponse>(response.Result, new PrefClassJsonConverter()); 

Ou exactement ce que vous veux être plus élégant?

+0

Ceci est certainement plus élégant que de passer un certain nombre d'initialiseurs imbriqués à 'Content.ReadAsAsync()'. Le seul inconvénient est probablement de lire le flux dans une chaîne qui est plus que parfaite pour les paquets json pas très gros. J'ai changé mon code de cette façon après sa sortie de la fenêtre de l'éditeur de code, et aucun formatage ne l'a aidé. –

1

j'ai pu ajouter une coutume JsonConverter aux formatteurs par défaut HttpClient avec ce qui suit:

MediaTypeFormatterCollection formatters = new MediaTypeFormatterCollection(); 
formatters.JsonFormatter.SerializerSettings.Converters.Add(new MyCustomConverter()); 


var result = response.Content.ReadAsAsync<T>(formatters).Result; 

Ceci semblait vous permettre d'ajouter simplement votre convertisseur personnalisé au convertisseurs par défaut.

Questions connexes