@@ -89,9 +89,9 @@ public string Serialize(object obj)
8989 return JsonConvert . SerializeObject ( obj , _serializerSettings ) ;
9090 }
9191
92- public T Deserialize < T > ( HttpResponseMessage response )
92+ public async Task < T > DeserializeAsync < T > ( HttpResponseMessage response )
9393 {
94- var result = ( T ) Deserialize ( response , typeof ( T ) ) ;
94+ var result = ( T ) await DeserializeAsync ( response , typeof ( T ) ) . ConfigureAwait ( false ) ;
9595 return result ;
9696 }
9797
@@ -101,17 +101,17 @@ public T Deserialize<T>(HttpResponseMessage response)
101101 /// <param name="response">The HTTP response.</param>
102102 /// <param name="type">Object type.</param>
103103 /// <returns>Object representation of the JSON string.</returns>
104- internal object Deserialize ( HttpResponseMessage response , Type type )
104+ internal async Task < object > DeserializeAsync ( HttpResponseMessage response , Type type )
105105 {
106106 IList < string > headers = response . Headers . Select ( x => x . Key + "=" + x . Value ) . ToList ( ) ;
107107
108108 if ( type == typeof ( byte [ ] ) ) // return byte array
109- return response . Content . ReadAsByteArrayAsync ( ) . Result ;
109+ return await response . Content . ReadAsByteArrayAsync ( ) . ConfigureAwait ( false ) ;
110110
111111 // TODO: ? if (type.IsAssignableFrom(typeof(Stream)))
112112 if ( type == typeof ( Stream ) )
113113 {
114- var bytes = response . Content . ReadAsByteArrayAsync ( ) . Result ;
114+ var bytes = await response . Content . ReadAsByteArrayAsync ( ) . ConfigureAwait ( false ) ;
115115 if ( headers != null )
116116 {
117117 var filePath = string . IsNullOrEmpty ( _configuration . TempFolderPath )
@@ -137,16 +137,16 @@ internal object Deserialize(HttpResponseMessage response, Type type)
137137 }
138138
139139 if ( type . Name . StartsWith ( "System.Nullable`1[[System.DateTime" ) ) // return a datetime object
140- return DateTime . Parse ( response . Content . ReadAsStringAsync ( ) . Result , null ,
140+ return DateTime . Parse ( await response . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) , null ,
141141 System . Globalization . DateTimeStyles . RoundtripKind ) ;
142142
143143 if ( type == typeof ( string ) || type . Name . StartsWith ( "System.Nullable" ) ) // return primitive type
144- return Convert . ChangeType ( response . Content . ReadAsStringAsync ( ) . Result , type ) ;
144+ return Convert . ChangeType ( await response . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) , type ) ;
145145
146146 // at this point, it must be a model (json)
147147 try
148148 {
149- return JsonConvert . DeserializeObject ( response . Content . ReadAsStringAsync ( ) . Result , type ,
149+ return JsonConvert . DeserializeObject ( await response . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) , type ,
150150 _serializerSettings ) ;
151151 }
152152 catch ( Exception e )
@@ -157,7 +157,7 @@ internal object Deserialize(HttpResponseMessage response, Type type)
157157 }
158158
159159 /// <summary>
160- /// Provides a default implementation of an Api client (both synchronous and asynchronous implementatios ),
160+ /// Provides a default implementation of an Api client (both synchronous and asynchronous implementations ),
161161 /// encapsulating general REST accessor use cases.
162162 /// </summary>
163163 /// <remarks>
@@ -393,12 +393,12 @@ private HttpRequestMessage NewRequest(
393393 return request ;
394394 }
395395
396- private ApiResponse < T > ToApiResponse < T > ( HttpResponseMessage response , object responseData , Uri uri )
396+ private async Task < ApiResponse < T > > ToApiResponseAsync < T > ( HttpResponseMessage response , object responseData , Uri uri )
397397 {
398398 var result = ( T ) responseData ;
399399 string rawContent = response . Content . ToString ( ) ;
400400 if ( ! response . IsSuccessStatusCode )
401- rawContent = response . Content . ReadAsStringAsync ( ) . Result ;
401+ rawContent = await response . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) ;
402402
403403 var transformed =
404404 new ApiResponse < T > ( response . StatusCode , new Multimap < string , string > ( ) , result , rawContent )
@@ -432,7 +432,7 @@ private ApiResponse<T> ToApiResponse<T>(HttpResponseMessage response, object res
432432
433433 private ApiResponse < T > Exec < T > ( HttpRequestMessage req , IReadableConfiguration configuration )
434434 {
435- return ExecAsync < T > ( req , configuration ) . Result ;
435+ return ExecAsync < T > ( req , configuration ) . GetAwaiter ( ) . GetResult ( ) ;
436436 }
437437
438438 private async Task < ApiResponse < T > > ExecAsync < T > ( HttpRequestMessage req ,
@@ -441,73 +441,82 @@ private async Task<ApiResponse<T>> ExecAsync<T>(HttpRequestMessage req,
441441 {
442442 var deserializer = new CustomJsonCodec ( SerializerSettings , configuration ) ;
443443
444+ CancellationTokenSource timeoutCancellationTokenSource = null ;
444445 var finalToken = cancellationToken ;
445446
446- if ( configuration . Timeout > 0 )
447+ try
447448 {
448- var tokenSource = new CancellationTokenSource ( configuration . Timeout ) ;
449- finalToken = CancellationTokenSource . CreateLinkedTokenSource ( finalToken , tokenSource . Token ) . Token ;
450- }
449+ if ( configuration . Timeout > 0 )
450+ {
451+ timeoutCancellationTokenSource = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
452+ timeoutCancellationTokenSource . CancelAfter ( configuration . Timeout ) ;
453+ finalToken = timeoutCancellationTokenSource . Token ;
454+ }
451455
452- if ( configuration . Proxy != null )
453- {
454- if ( _httpClientHandler == null )
455- throw new InvalidOperationException (
456- "Configuration `Proxy` not supported when the client is explicitly created without an HttpClientHandler, use the proper constructor." ) ;
457- _httpClientHandler . Proxy = configuration . Proxy ;
458- }
456+ if ( configuration . Proxy != null )
457+ {
458+ if ( _httpClientHandler == null )
459+ throw new InvalidOperationException (
460+ "Configuration `Proxy` not supported when the client is explicitly created without an HttpClientHandler, use the proper constructor." ) ;
461+ _httpClientHandler . Proxy = configuration . Proxy ;
462+ }
459463
460- if ( configuration . ClientCertificates != null )
461- {
462- if ( _httpClientHandler == null )
463- throw new InvalidOperationException (
464- "Configuration `ClientCertificates` not supported when the client is explicitly created without an HttpClientHandler, use the proper constructor." ) ;
465- _httpClientHandler . ClientCertificates . AddRange ( configuration . ClientCertificates ) ;
466- }
464+ if ( configuration . ClientCertificates != null )
465+ {
466+ if ( _httpClientHandler == null )
467+ throw new InvalidOperationException (
468+ "Configuration `ClientCertificates` not supported when the client is explicitly created without an HttpClientHandler, use the proper constructor." ) ;
469+ _httpClientHandler . ClientCertificates . AddRange ( configuration . ClientCertificates ) ;
470+ }
467471
468- var cookieContainer = req . Properties . ContainsKey ( "CookieContainer" )
469- ? req . Properties [ "CookieContainer" ] as List < Cookie >
470- : null ;
472+ var cookieContainer = req . Properties . ContainsKey ( "CookieContainer" )
473+ ? req . Properties [ "CookieContainer" ] as List < Cookie >
474+ : null ;
471475
472- if ( cookieContainer != null )
473- {
474- if ( _httpClientHandler == null )
475- throw new InvalidOperationException (
476- "Request property `CookieContainer` not supported when the client is explicitly created without an HttpClientHandler, use the proper constructor." ) ;
477- foreach ( var cookie in cookieContainer ) _httpClientHandler . CookieContainer . Add ( cookie ) ;
478- }
476+ if ( cookieContainer != null )
477+ {
478+ if ( _httpClientHandler == null )
479+ throw new InvalidOperationException (
480+ "Request property `CookieContainer` not supported when the client is explicitly created without an HttpClientHandler, use the proper constructor." ) ;
481+ foreach ( var cookie in cookieContainer ) _httpClientHandler . CookieContainer . Add ( cookie ) ;
482+ }
479483
480- HttpResponseMessage response ;
481- if ( RetryConfiguration . AsyncRetryPolicy != null )
482- {
483- var policy = RetryConfiguration . AsyncRetryPolicy ;
484- var policyResult = await policy
485- . ExecuteAndCaptureAsync ( ( ) => _httpClient . SendAsync ( req , cancellationToken ) )
486- . ConfigureAwait ( false ) ;
487- response = policyResult . Outcome == OutcomeType . Successful
488- ? policyResult . Result
489- : new HttpResponseMessage
490- {
491- ReasonPhrase = policyResult . FinalException . ToString ( ) ,
492- RequestMessage = req
493- } ;
494- }
495- else
496- {
497- response = await _httpClient . SendAsync ( req , cancellationToken ) . ConfigureAwait ( false ) ;
498- }
484+ HttpResponseMessage response ;
485+ if ( RetryConfiguration . AsyncRetryPolicy != null )
486+ {
487+ var policy = RetryConfiguration . AsyncRetryPolicy ;
488+ var policyResult = await policy
489+ . ExecuteAndCaptureAsync ( ( ) => _httpClient . SendAsync ( req , finalToken ) )
490+ . ConfigureAwait ( false ) ;
491+ response = policyResult . Outcome == OutcomeType . Successful
492+ ? policyResult . Result
493+ : new HttpResponseMessage
494+ {
495+ ReasonPhrase = policyResult . FinalException . ToString ( ) ,
496+ RequestMessage = req
497+ } ;
498+ }
499+ else
500+ {
501+ response = await _httpClient . SendAsync ( req , finalToken ) . ConfigureAwait ( false ) ;
502+ }
499503
500- object responseData = deserializer . Deserialize < T > ( response ) ;
504+ object responseData = await deserializer . DeserializeAsync < T > ( response ) . ConfigureAwait ( false ) ;
501505
502- // if the response type is oneOf/anyOf, call FromJSON to deserialize the data
503- if ( typeof ( AbstractOpenAPISchema ) . IsAssignableFrom ( typeof ( T ) ) )
504- responseData = ( T ) typeof ( T ) . GetMethod ( "FromJson" ) ? . Invoke ( null , new object [ ] { response . Content } ) ;
505- else if ( typeof ( T ) . Name == "Stream" ) // for binary response
506- responseData = ( T ) ( object ) await response . Content . ReadAsStreamAsync ( ) ;
506+ // if the response type is oneOf/anyOf, call FromJSON to deserialize the data
507+ if ( typeof ( AbstractOpenAPISchema ) . IsAssignableFrom ( typeof ( T ) ) )
508+ responseData = ( T ) typeof ( T ) . GetMethod ( "FromJson" ) ? . Invoke ( null , new object [ ] { response . Content } ) ;
509+ else if ( typeof ( T ) . Name == "Stream" ) // for binary response
510+ responseData = ( T ) ( object ) await response . Content . ReadAsStreamAsync ( ) . ConfigureAwait ( false ) ;
507511
508- var result = ToApiResponse < T > ( response , responseData , req . RequestUri ) ;
512+ var result = await ToApiResponseAsync < T > ( response , responseData , req . RequestUri ) . ConfigureAwait ( false ) ;
509513
510- return result ;
514+ return result ;
515+ }
516+ finally
517+ {
518+ timeoutCancellationTokenSource ? . Dispose ( ) ;
519+ }
511520 }
512521
513522 #region IAsynchronousClient
0 commit comments