2012-12-17 16 views
13

Używam HttpClient .NET do wysyłania żądań do WebAPI, który zwraca niektóre dane JSON, które wymagają trochę niestandardowej deserializacji po stronie klienta. W tym celu stworzyłem własne JsonConverter, ale nie mogę się dowiedzieć, w jaki sposób metoda ReadAsAsync<T> odbiera istnienie konwertera..net HttpClient z niestandardowym JsonConverter

Rozwiązałem mój problem na teraz, używając ReadAsStringAsync, aby odczytać odpowiedź, a następnie przekazując ten ciąg do JsonConvert.DeserializeObject, ale wydaje się, że powinno być bardziej eleganckie rozwiązanie.

Oto mój kod:

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

Czy to najlepsze, co mogę zrobić, czy jest tam jakiś bardziej elegancki sposób?

Oto gdzie jestem tworzenia httpclient także, jeśli to gdzie muszę go podłączyć:

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

Odpowiedz

13

Można zdać JsonSerializerSettings z listy swoich konwerterów do JsonMediaTypeFormatter który będzie używany przez ReadAsAsync<T>:

tj

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

Nie miałem pojęcia, że ​​JSON.Net ma własną koncepcję konwerterów! Teraz mamy trzy rzeczy, które mogą wykonać tę samą pracę. Pochodne klasy HttpContent, pochodne MediaTypeFormatters i wyprowadzone JsonConverter .... –

+0

Tego właśnie szukałem. W końcu zamierzam z tym, co pierwotnie miałem, ponieważ muszę również buforować odpowiedź na dysku w przypadku awarii na przyszłych żądaniach. –

+0

Cudownie! Musiałem dostosować niektóre inne ustawienia JSON.NET i to był brakujący fragment układanki dla mnie :) –

1

Może chcesz użyć HttpClient.GetStringAsync Method (String)

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

czy co dokładnie ci chcesz być bardziej elegancki?

+0

Jest to zdecydowanie bardziej eleganckie niż przekazywanie piekła inicjatorów zagnieżdżonych do 'Content.ReadAsAsync()'. Jedyne minusy prawdopodobnie czytają strumień w łańcuchu, który jest niezły w przypadku niezbyt dużych pakietów json. W ten sposób zmieniłem kod po wyjściu z okna edytora kodu i żadne formatowanie nie pomaga w tym. –

1

udało mi się dodać niestandardowe JsonConverter do domyślnych formatujących dla HttpClient z następującym:

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


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

To wydawało się umożliwiać dodanie niestandardowego konwertera do domyślne konwertery.

Powiązane problemy