2012-12-17 33 views
13

Tôi đang sử dụng HttpClient của .NET để đưa ra yêu cầu cho WebAPI trả về một số dữ liệu JSON yêu cầu một chút tùy chỉnh deserialization ở phía máy khách. Đối với điều này tôi đã thực hiện của riêng tôi JsonConverter, nhưng tôi không thể tìm ra cách để có phương pháp ReadAsAsync<T> nhận sự tồn tại của bộ chuyển đổi.. HttpClient với tùy chỉnh JsonConverter

Tôi đã giải quyết được vấn đề của mình ngay bây giờ bằng cách sử dụng ReadAsStringAsync để đọc câu trả lời, sau đó chuyển chuỗi đó vào JsonConvert.DeserializeObject, nhưng có vẻ như cần có giải pháp thanh lịch hơn.

Dưới đây là mã của tôi:

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

Đây có phải là tốt nhất tôi có thể làm, hoặc là có một số cách thanh lịch hơn?

Đây là nơi tôi đang tạo ra HttpClient cũng có, nếu đó là nơi tôi cần phải móc nó lên:

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

Trả lời

13

Bạn có thể vượt qua JsonSerializerSettings với danh sách các bộ chuyển đổi của mình vào JsonMediaTypeFormatter mà sẽ được sử dụng bởi ReadAsAsync<T>:

tức

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

Tôi không biết JSON.Net có khái niệm riêng về chuyển đổi! Vì vậy, bây giờ chúng tôi có ba điều có thể làm cùng một công việc. Các lớp HttpContent có nguồn gốc, xuất phát từ MediaTypeFormatters và dẫn xuất JsonConverter .... –

+0

Đây là những gì tôi đang tìm kiếm. Cuối cùng tôi sẽ đi với những gì tôi ban đầu đã có mặc dù kể từ khi tôi cũng cần phải cache các phản ứng trên đĩa trong trường hợp thất bại trên các yêu cầu trong tương lai. –

+0

Tuyệt vời! Tôi cần phải tùy chỉnh một số cài đặt JSON.NET khác và đây là phần thiếu của câu đố cho tôi :) –

1

Có thể bạn muốn sử dụng HttpClient.GetStringAsync Method (String)

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

Hoặc chính xác những gì bạn muốn thanh lịch hơn?

+0

Điều này chắc chắn thanh lịch hơn là truyền một địa chỉ khởi tạo lồng vào 'Content.ReadAsAsync()'. Các khuyết điểm duy nhất có lẽ là đọc luồng vào một chuỗi mà là tốt hơn cho các gói json không phải là rất lớn. Tôi đã thay đổi mã của mình theo cách này sau khi nó đã đi ra ngoài cửa sổ trình soạn thảo mã và không có định dạng nào giúp với nó. –

1

tôi đã có thể để thêm một JsonConverter tùy chỉnh cho trình định dạng mặc định cho HttpClient với những điều sau đây:

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


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

Điều này dường như cho phép bạn thêm công cụ chuyển đổi tùy chỉnh của bạn vào bộ chuyển đổi mặc định.

Các vấn đề liên quan