/// <summary> /// Executes the HttpCall. This will generate the headers, create the request and populate the HttpCall properties with /// relevant data. /// The HttpCall may only be called once; further attempts to execute the same call will throw an /// InvalidOperationException. /// </summary> /// <returns>HttpCall with populated data</returns> public async Task <HttpCall> Execute() { if (Executed) { throw new InvalidOperationException("A HttpCall can only be executed once"); } var req = new HttpRequestMessage(_method, new Uri(_url)); // Setting header if (_headers != null) { if (_headers.Authorization != null) { req.Headers.Authorization = _headers.Authorization; } foreach (var item in _headers.Headers) { req.Headers[item.Key] = item.Value; } } // if the user agent has not yet been set, set it; we want to make sure this only really happens once since it requires an action that goes to the core thread. if (String.IsNullOrWhiteSpace(UserAgentHeader)) { var task = new TaskCompletionSource <string>(); await Task.Run(async() => { await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( CoreDispatcherPriority.Normal, async() => { await GenerateUserAgentHeader(); task.SetResult(UserAgentHeader); }); }); await task.Task; } req.Headers.UserAgent.TryParseAdd(UserAgentHeader); if (!String.IsNullOrWhiteSpace(_requestBody)) { switch (_contentType) { case ContentTypeValues.FormUrlEncoded: req.Content = new HttpFormUrlEncodedContent(_requestBody.ParseQueryString()); break; default: req.Content = new HttpStringContent(_requestBody); req.Content.Headers.ContentType = new HttpMediaTypeHeaderValue(_contentType.MimeType()); break; } } HttpResponseMessage message; try { message = await _webClient.SendRequestAsync(req); HandleMessageResponse(message); } catch (Exception ex) { _httpCallErrorException = ex; message = null; } return(this); }
/// <summary> /// Executes the HttpCall. This will generate the headers, create the request and populate the HttpCall properties with /// relevant data. /// The HttpCall may only be called once; further attempts to execute the same call will throw an /// InvalidOperationException. /// </summary> /// <param name="cancellationToken"></param> /// <returns>HttpCall with populated data</returns> public async Task <HttpCall> ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (Executed) { throw new InvalidOperationException("A HttpCall can only be executed once"); } var req = new HttpRequestMessage(_method, new Uri(_url)); // Setting header if (_headers != null) { if (_headers.Authorization != null) { req.Headers.Authorization = _headers.Authorization; } foreach (var item in _headers.Headers) { req.Headers.Add(item.Key, item.Value); } } // if the user agent has not yet been set, set it; we want to make sure this only really happens once since it requires an action that goes to the core thread. if (String.IsNullOrWhiteSpace(UserAgentHeader)) { UserAgentHeader = await SDKServiceLocator.Get <IApplicationInformationService>().GenerateUserAgentHeaderAsync(false, String.Empty); } req.Headers.UserAgent.TryParseAdd(UserAgentHeader); if (!String.IsNullOrWhiteSpace(_requestBody)) { switch (_contentType) { case ContentTypeValues.FormUrlEncoded: req.Content = new FormUrlEncodedContent(_requestBody.ParseQueryString()); break; case ContentTypeValues.Gzip: req.Content = await CompressAsync(new StringContent(_requestBody)); break; default: req.Content = new StringContent(_requestBody); req.Content.Headers.ContentType = new MediaTypeHeaderValue(_contentType.MimeType()); break; } } HttpResponseMessage message; try { message = await _httpClient.SendAsync(req, cancellationToken); } catch (HttpRequestException ex) { _httpCallErrorException = new DeviceOfflineException("Request failed to send, most likely because we were offline", ex); return(this); } catch (WebException ex) { _httpCallErrorException = new DeviceOfflineException("Request failed to send, most likely because we were offline", ex); return(this); } // If the result is null then it might be because the http call was canceled. // HttpClient has a bug where it doesn't throw when a cancellation is requested, // it just returns null immediately (however the cancellation token does get set // to canceled). More context on that bug at: // http://stackoverflow.com/questions/29319086/cancelling-an-httpclient-request-why-is-taskcanceledexception-cancellationtoke // The following if block will throw an OperationCanceledException (which is the // desired behavior for when a Task gets canceled) if a cancel was requested // and works around the HttpClient bug. if (message == null) { cancellationToken.ThrowIfCancellationRequested(); } await HandleMessageResponseAsync(message); return(this); }
/// <summary> /// Executes the HttpCall. This will generate the headers, create the request and populate the HttpCall properties with /// relevant data. /// The HttpCall may only be called once; further attempts to execute the same call will throw an /// InvalidOperationException. /// </summary> /// <returns>HttpCall with populated data</returns> public async Task <HttpCall> ExecuteAsync() { if (Executed) { throw new InvalidOperationException("A HttpCall can only be executed once"); } var req = new HttpRequestMessage(_method, new Uri(_url)); // Setting header if (_headers != null) { if (_headers.Authorization != null) { req.Headers.Authorization = _headers.Authorization; } foreach (var item in _headers.Headers) { req.Headers.Add(item.Key, item.Value); } } // if the user agent has not yet been set, set it; we want to make sure this only really happens once since it requires an action that goes to the core thread. if (String.IsNullOrWhiteSpace(UserAgentHeader)) { UserAgentHeader = await SDKServiceLocator.Get <IApplicationInformationService>().GenerateUserAgentHeaderAsync(false, String.Empty); } req.Headers.UserAgent.TryParseAdd(UserAgentHeader); if (!String.IsNullOrWhiteSpace(_requestBody)) { switch (_contentType) { case ContentTypeValues.FormUrlEncoded: req.Content = new FormUrlEncodedContent(_requestBody.ParseQueryString()); break; default: req.Content = new StringContent(_requestBody); req.Content.Headers.ContentType = new MediaTypeHeaderValue(_contentType.MimeType()); break; } } HttpResponseMessage message; try { message = await _httpClient.SendAsync(req); } catch (HttpRequestException ex) { _httpCallErrorException = new DeviceOfflineException("Request failed to send, most likely because we were offline", ex); return(this); } catch (WebException ex) { _httpCallErrorException = new DeviceOfflineException("Request failed to send, most likely because we were offline", ex); return(this); } await HandleMessageResponseAsync(message); return(this); }