예제 #1
0
        public override Task AbandonAsync(string lockToken, CancellationToken cancellationToken)
        {
            var customHeaders = PrepareCustomHeaders(
                CommonConstants.DeviceBoundPathAbandonTemplate.FormatInvariant(this.deviceId, lockToken),
                null,
                CommonConstants.CloudToDeviceOperation);

            // Even though If-Match is not a customHeader, add it here for convenience
            customHeaders.Add(HttpRequestHeader.IfMatch.ToString(), lockToken);

            return(this.HandleTimeoutCancellation(() =>
                                                  this.httpClientHelper.PostAsync(
                                                      GetRequestUri(this.deviceId, CommonConstants.DeviceBoundPathTemplate + "/{0}/abandon".FormatInvariant(lockToken), null),
                                                      (Object)null,
                                                      ExceptionHandlingHelper.GetDefaultErrorMapping(),
                                                      customHeaders,
                                                      cancellationToken), cancellationToken));
        }
        public override Task CompleteAsync(string lockToken, CancellationToken cancellationToken)
        {
            IDictionary <string, string> customHeaders = PrepareCustomHeaders(
                CommonConstants.DeviceBoundPathCompleteTemplate.FormatInvariant(_deviceId, lockToken),
                null,
                CommonConstants.CloudToDeviceOperation);

            var eTag = new ETagHolder {
                ETag = lockToken
            };

            return(_httpClientHelper.DeleteAsync(
                       GetRequestUri(_deviceId, CommonConstants.DeviceBoundPathTemplate + "/{0}".FormatInvariant(lockToken), null),
                       eTag,
                       ExceptionHandlingHelper.GetDefaultErrorMapping(),
                       customHeaders,
                       cancellationToken));
        }
예제 #3
0
        public async Task GetExceptionCodeAsync_NoContentErrorCode_InvalidErrorCode()
        {
            // arrange
            var httpResponseMessage = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest);
            var exceptionResult     = new IoTHubExceptionResult
            {
                Message = ""
            };

            httpResponseMessage.Content = new StringContent(JsonConvert.SerializeObject(exceptionResult));
            httpResponseMessage.Headers.Add(CommonConstants.HttpErrorCodeName, "DeviceNotFound");

            // act
            ErrorCode errorCode = await ExceptionHandlingHelper.GetExceptionCodeAsync(httpResponseMessage);

            // assert
            Assert.AreEqual(ErrorCode.InvalidErrorCode, errorCode);
        }
예제 #4
0
        protected override Task OnSendEventAsync(IEnumerable <Message> messages)
        {
            if (messages == null)
            {
                throw Fx.Exception.ArgumentNull("messages");
            }

            var customHeaders = PrepareCustomHeaders(CommonConstants.DeviceEventPathTemplate.FormatInvariant(this.deviceId), string.Empty, CommonConstants.DeviceToCloudOperation);

            string body = ToJson(messages);

            return(this.httpClientHelper.PostAsync <string>(
                       GetRequestUri(this.deviceId, CommonConstants.DeviceEventPathTemplate, null),
                       body,
                       ExceptionHandlingHelper.GetDefaultErrorMapping(),
                       customHeaders,
                       CancellationToken.None));
        }
예제 #5
0
        protected override Task OnCompleteAsync(string lockToken)
        {
            var customHeaders = PrepareCustomHeaders(
                CommonConstants.DeviceBoundPathCompleteTemplate.FormatInvariant(this.deviceId, lockToken),
                null,
                CommonConstants.CloudToDeviceOperation);

            var eTag = new ETagHolder {
                ETag = lockToken
            };

            return(this.httpClientHelper.DeleteAsync(
                       GetRequestUri(this.deviceId, CommonConstants.DeviceBoundPathTemplate + "/{0}".FormatInvariant(lockToken), null),
                       eTag,
                       ExceptionHandlingHelper.GetDefaultErrorMapping(),
                       customHeaders,
                       CancellationToken.None));
        }
예제 #6
0
        static async Task <Exception> MapToExceptionAsync(
            HttpResponseMessage response,
            IDictionary <HttpStatusCode, Func <HttpResponseMessage, Task <Exception> > > errorMapping)
        {
            Func <HttpResponseMessage, Task <Exception> > func;

            if (!errorMapping.TryGetValue(response.StatusCode, out func))
            {
                return(new IotHubException(
                           await ExceptionHandlingHelper.GetExceptionMessageAsync(response),
                           isTransient: true));
            }

            var mapToExceptionFunc = errorMapping[response.StatusCode];
            var exception          = mapToExceptionFunc(response);

            return(await exception);
        }
예제 #7
0
        internal HttpTransportHandler(IPipelineContext context, IotHubConnectionString iotHubConnectionString, Http1TransportSettings transportSettings, HttpClientHandler httpClientHandler = null)
            : base(context, transportSettings)
        {
            ProductInfo productInfo = context.Get <ProductInfo>();

            this.deviceId         = iotHubConnectionString.DeviceId;
            this.moduleId         = iotHubConnectionString.ModuleId;
            this.httpClientHelper = new HttpClientHelper(
                iotHubConnectionString.HttpsEndpoint,
                iotHubConnectionString,
                ExceptionHandlingHelper.GetDefaultErrorMapping(),
                DefaultOperationTimeout,
                null,
                transportSettings.ClientCertificate,
                httpClientHandler,
                productInfo,
                transportSettings.Proxy);
        }
        public override async Task AbandonAsync(string lockToken, CancellationToken cancellationToken)
        {
            IDictionary <string, string> customHeaders = PrepareCustomHeaders(
                CommonConstants.DeviceBoundPathAbandonTemplate.FormatInvariant(_deviceId, lockToken),
                null,
                CommonConstants.CloudToDeviceOperation);

            // Even though If-Match is not a customHeader, add it here for convenience
            customHeaders.Add(HttpRequestHeader.IfMatch.ToString(), lockToken);

            await _httpClientHelper
            .PostAsync(
                GetRequestUri(_deviceId, CommonConstants.DeviceBoundPathTemplate + "/{0}/abandon".FormatInvariant(lockToken), null),
                (object)null,
                ExceptionHandlingHelper.GetDefaultErrorMapping(),
                customHeaders,
                cancellationToken)
            .ConfigureAwait(false);
        }
        public override Task SendEventAsync(IEnumerable <Message> messages, CancellationToken cancellationToken)
        {
            if (messages == null)
            {
                throw Fx.Exception.ArgumentNull(nameof(messages));
            }

            cancellationToken.ThrowIfCancellationRequested();

            var customHeaders = PrepareCustomHeaders(CommonConstants.DeviceEventPathTemplate.FormatInvariant(_deviceId), string.Empty, CommonConstants.DeviceToCloudOperation);

            string body = ToJson(messages);

            return(_httpClientHelper.PostAsync <string>(
                       GetRequestUri(_deviceId, CommonConstants.DeviceEventPathTemplate, null),
                       body,
                       ExceptionHandlingHelper.GetDefaultErrorMapping(),
                       customHeaders,
                       cancellationToken));
        }
        public override Task RejectAsync(string lockToken, CancellationToken cancellationToken)
        {
            var customHeaders = PrepareCustomHeaders(
                CommonConstants.DeviceBoundPathRejectTemplate.FormatInvariant(this.deviceId, lockToken),
                null,
                CommonConstants.CloudToDeviceOperation);

            var eTag = new ETagHolder {
                ETag = lockToken
            };

            return(this.HandleTimeoutCancellation(() =>
                                                  this.httpClientHelper.DeleteAsync(
                                                      GetRequestUri(this.deviceId, CommonConstants.DeviceBoundPathTemplate + "/{0}".FormatInvariant(lockToken), new Dictionary <string, string>
            {
                { "reject", null }
            }),
                                                      eTag,
                                                      ExceptionHandlingHelper.GetDefaultErrorMapping(),
                                                      customHeaders,
                                                      cancellationToken), cancellationToken));
        }
        internal HttpTransportHandler(
            PipelineContext context,
            IotHubConnectionString iotHubConnectionString,
            Http1TransportSettings transportSettings,
            HttpClientHandler httpClientHandler  = null,
            bool isClientPrimaryTransportHandler = false)
            : base(context, transportSettings)
        {
            ProductInfo productInfo = context.ProductInfo;

            _deviceId         = iotHubConnectionString.DeviceId;
            _moduleId         = iotHubConnectionString.ModuleId;
            _httpClientHelper = new HttpClientHelper(
                iotHubConnectionString.HttpsEndpoint,
                iotHubConnectionString,
                ExceptionHandlingHelper.GetDefaultErrorMapping(),
                s_defaultOperationTimeout,
                null,
                transportSettings.ClientCertificate,
                httpClientHandler,
                productInfo,
                transportSettings.Proxy,
                isClientPrimaryTransportHandler);
        }
예제 #12
0
        public override async Task <Message> ReceiveAsync(TimeSpan timeout, CancellationToken cancellationToken)
        {
            // Long-polling is not supported
            if (!TimeSpan.Zero.Equals(timeout))
            {
                throw new ArgumentOutOfRangeException(nameof(timeout), "Http Protocol does not support a non-zero receive timeout");
            }

            cancellationToken.ThrowIfCancellationRequested();

            IDictionary <string, string> customHeaders        = PrepareCustomHeaders(CommonConstants.DeviceBoundPathTemplate.FormatInvariant(this.deviceId), null, CommonConstants.CloudToDeviceOperation);
            IDictionary <string, string> queryValueDictionary =
                new Dictionary <string, string>()
            {
                { CustomHeaderConstants.MessageLockTimeout, DefaultOperationTimeout.TotalSeconds.ToString(CultureInfo.InvariantCulture) }
            };

            HttpResponseMessage responseMessage = await this.httpClientHelper.GetAsync <HttpResponseMessage>(
                GetRequestUri(this.deviceId, CommonConstants.DeviceBoundPathTemplate, queryValueDictionary),
                ExceptionHandlingHelper.GetDefaultErrorMapping(),
                customHeaders,
                true,
                cancellationToken).ConfigureAwait(false);

            if (responseMessage == null || responseMessage.StatusCode == HttpStatusCode.NoContent)
            {
                return(null);
            }

            IEnumerable <string> messageId;

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.MessageId, out messageId);

            IEnumerable <string> lockToken;

            responseMessage.Headers.TryGetValues(HttpResponseHeader.ETag.ToString(), out lockToken);

            IEnumerable <string> enqueuedTime;

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.EnqueuedTime, out enqueuedTime);

            IEnumerable <string> deliveryCountAsStr;

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.DeliveryCount, out deliveryCountAsStr);

            IEnumerable <string> expiryTime;

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.ExpiryTimeUtc, out expiryTime);

            IEnumerable <string> correlationId;

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.CorrelationId, out correlationId);

            IEnumerable <string> sequenceNumber;

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.SequenceNumber, out sequenceNumber);

            byte[] byteContent = await responseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);

            var message = byteContent != null ? new Message(byteContent) : new Message();

            message.MessageId = messageId != null?messageId.First() : null;

            message.LockToken = lockToken != null?lockToken.First().Trim('\"') : null;

            if (enqueuedTime != null)
            {
                DateTime enqueuedTimeUtc;
                if (DateTime.TryParse(enqueuedTime.First(), out enqueuedTimeUtc))
                {
                    message.EnqueuedTimeUtc = enqueuedTimeUtc;
                }
            }

            if (deliveryCountAsStr != null)
            {
                byte deliveryCount;
                if (byte.TryParse(deliveryCountAsStr.First(), out deliveryCount))
                {
                    message.DeliveryCount = deliveryCount;
                }
            }

            if (expiryTime != null)
            {
                DateTime absoluteExpiryTime;
                if (DateTime.TryParse(expiryTime.First(), out absoluteExpiryTime))
                {
                    message.ExpiryTimeUtc = absoluteExpiryTime;
                }
            }

            message.CorrelationId = correlationId != null?correlationId.First() : null;

            message.SequenceNumber = sequenceNumber != null?Convert.ToUInt64(sequenceNumber.First()) : 0;

            // Read custom headers and map them to properties.
            foreach (KeyValuePair <string, IEnumerable <string> > keyValue in responseMessage.Headers)
            {
                if (keyValue.Key.StartsWith(CustomHeaderConstants.HttpAppPropertyPrefix, StringComparison.OrdinalIgnoreCase))
                {
                    message.Properties.Add(keyValue.Key.Substring(CustomHeaderConstants.HttpAppPropertyPrefix.Length), keyValue.Value.First());
                }
            }

            return(message);
        }
예제 #13
0
        internal async Task UploadToBlobAsync(string blobName, Stream source, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var fileUploadRequest = new FileUploadRequest()
            {
                BlobName = blobName
            };

            var fileUploadResponse = await this.httpClientHelper.PostAsync <FileUploadRequest, FileUploadResponse>(
                GetRequestUri(this.deviceId, CommonConstants.BlobUploadPathTemplate, null),
                fileUploadRequest,
                ExceptionHandlingHelper.GetDefaultErrorMapping(),
                null,
                cancellationToken).ConfigureAwait(false);

            string putString = String.Format(
                CultureInfo.InvariantCulture,
                "https://{0}/{1}/{2}{3}",
                fileUploadResponse.HostName,
                fileUploadResponse.ContainerName,
                Uri.EscapeDataString(fileUploadResponse.BlobName), // Pass URL encoded device name and blob name to support special characters
                fileUploadResponse.SasToken);

            var notification = new FileUploadNotificationResponse();

            try
            {
                // 2. Use SAS URI to send data to Azure Storage Blob (PUT)
                CloudBlockBlob blob       = new CloudBlockBlob(new Uri(putString));
                var            uploadTask = blob.UploadFromStreamAsync(source);
                await uploadTask.ConfigureAwait(false);

                notification.CorrelationId     = fileUploadResponse.CorrelationId;
                notification.IsSuccess         = uploadTask.IsCompleted;
                notification.StatusCode        = uploadTask.IsCompleted ? 0 : -1;
                notification.StatusDescription = uploadTask.IsCompleted ? null : "Failed to upload to storage.";

                // 3. POST to IoTHub with upload status
                await this.httpClientHelper.PostAsync <FileUploadNotificationResponse>(
                    GetRequestUri(this.deviceId, CommonConstants.BlobUploadStatusPathTemplate + "notifications", null),
                    notification,
                    ExceptionHandlingHelper.GetDefaultErrorMapping(),
                    null,
                    cancellationToken).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex) when(!ex.IsFatal())
            {
                // 3. POST to IoTHub with upload status
                notification.IsSuccess         = false;
                notification.StatusCode        = -1;
                notification.StatusDescription = ex.Message;

                await this.httpClientHelper.PostAsync <FileUploadNotificationResponse>(
                    GetRequestUri(this.deviceId, CommonConstants.BlobUploadStatusPathTemplate + "notifications/" + fileUploadResponse.CorrelationId, null),
                    notification,
                    ExceptionHandlingHelper.GetDefaultErrorMapping(),
                    null,
                    cancellationToken).ConfigureAwait(false);

                throw;
            }
        }
        public override async Task <Message> ReceiveAsync(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            IDictionary <string, string> customHeaders = PrepareCustomHeaders(
                CommonConstants.DeviceBoundPathTemplate.FormatInvariant(_deviceId),
                null,
                CommonConstants.CloudToDeviceOperation);
            var queryValueDictionary = new Dictionary <string, string>
            {
                { CustomHeaderConstants.MessageLockTimeout, s_defaultOperationTimeout.TotalSeconds.ToString(CultureInfo.InvariantCulture) }
            };

            HttpResponseMessage responseMessage = await _httpClientHelper
                                                  .GetAsync <HttpResponseMessage>(
                GetRequestUri(_deviceId, CommonConstants.DeviceBoundPathTemplate, queryValueDictionary),
                ExceptionHandlingHelper.GetDefaultErrorMapping(),
                customHeaders,
                true,
                cancellationToken)
                                                  .ConfigureAwait(false);

            if (responseMessage == null ||
                responseMessage.StatusCode == HttpStatusCode.NoContent)
            {
                return(null);
            }

            byte[] byteContent = await responseMessage.Content
                                 .ReadHttpContentAsByteArrayAsync(cancellationToken)
                                 .ConfigureAwait(false);

            Message message = byteContent == null
                ? new Message()
                : new Message(byteContent);

            // Read Http headers and map them to message system properties.
            foreach (KeyValuePair <string, IEnumerable <string> > header in responseMessage.Headers)
            {
                string headerKey = header.Key;

                if (s_mapHttpHeadersToMessageProperties.ContainsKey(headerKey))
                {
                    string messagePropertyKey   = s_mapHttpHeadersToMessageProperties[headerKey];
                    object messagePropertyValue = ConvertToMessageSystemProperty(messagePropertyKey, header.Value);
                    if (messagePropertyValue != null)
                    {
                        message.SystemProperties[messagePropertyKey] = messagePropertyValue;
                    }
                }
            }

            // Read custom headers and map them to properties.
            foreach (KeyValuePair <string, IEnumerable <string> > keyValue in responseMessage.Headers)
            {
                if (keyValue.Key.StartsWith(CustomHeaderConstants.HttpAppPropertyPrefix, StringComparison.OrdinalIgnoreCase))
                {
                    message.Properties.Add(
                        keyValue.Key.Substring(CustomHeaderConstants.HttpAppPropertyPrefix.Length),
                        keyValue.Value.First());
                }
            }

            return(message);
        }
        internal async Task UploadToBlobAsync(String blobName, System.IO.Stream source)
        {
            // 1. Construct GET request to get SAS URI for storage account
            var responseMessage = await this.httpClientHelper.GetAsync <HttpResponseMessage>(
                GetRequestUri(this.deviceId, CommonConstants.BlobUploadPathTemplate + blobName, null),
                ExceptionHandlingHelper.GetDefaultErrorMapping(),
                null,
                true,
                CancellationToken.None);

            if (responseMessage.StatusCode != HttpStatusCode.OK)
            {
                throw new HttpRequestException(responseMessage.StatusCode.ToString());
            }

            var stringContent = await responseMessage.Content.ReadAsStringAsync();

            var getResponseData = JsonConvert.DeserializeObject <FileUploadGetResponse>(stringContent);

            string putString = String.Format("https://{0}/{1}/{2}{3}",
                                             getResponseData.HostName,
                                             getResponseData.ContainerName,
                                             getResponseData.BlobName,
                                             getResponseData.SasToken);

            FileUploadNotificationResponse notification = new FileUploadNotificationResponse();

            try
            {
                // 2. Use SAS URI to send data to Azure Storage Blob (PUT)
                CloudBlockBlob blob       = new CloudBlockBlob(new Uri(putString));
                var            uploadTask = blob.UploadFromStreamAsync(source);
                await          uploadTask;

                notification.IsSuccess         = uploadTask.IsCompleted;
                notification.StatusCode        = uploadTask.IsCompleted ? 0 : -1;
                notification.StatusDescription = uploadTask.IsCompleted ? null : "Failed to upload to storage.";

                // 3. POST to IoTHub with upload status
                await this.httpClientHelper.PostAsync <FileUploadNotificationResponse>(
                    GetRequestUri(this.deviceId, CommonConstants.BlobUploadPathTemplate + "notifications/" + getResponseData.CorrelationId, null),
                    notification,
                    ExceptionHandlingHelper.GetDefaultErrorMapping(),
                    null,
                    CancellationToken.None);
            }
            catch (Exception ex)
            {
                // 3. POST to IoTHub with upload status
                notification.IsSuccess         = false;
                notification.StatusCode        = -1;
                notification.StatusDescription = ex.Message;

                await this.httpClientHelper.PostAsync <FileUploadNotificationResponse>(
                    GetRequestUri(this.deviceId, CommonConstants.BlobUploadPathTemplate + "notifications/" + getResponseData.CorrelationId, null),
                    notification,
                    ExceptionHandlingHelper.GetDefaultErrorMapping(),
                    null,
                    CancellationToken.None);

                throw ex;
            }
        }
        public override async Task <Message> ReceiveAsync(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            IDictionary <string, string> customHeaders        = PrepareCustomHeaders(CommonConstants.DeviceBoundPathTemplate.FormatInvariant(_deviceId), null, CommonConstants.CloudToDeviceOperation);
            IDictionary <string, string> queryValueDictionary = new Dictionary <string, string>
            {
                { CustomHeaderConstants.MessageLockTimeout, s_defaultOperationTimeout.TotalSeconds.ToString(CultureInfo.InvariantCulture) }
            };

            HttpResponseMessage responseMessage = await _httpClientHelper
                                                  .GetAsync <HttpResponseMessage>(
                GetRequestUri(_deviceId, CommonConstants.DeviceBoundPathTemplate, queryValueDictionary),
                ExceptionHandlingHelper.GetDefaultErrorMapping(),
                customHeaders,
                true,
                cancellationToken)
                                                  .ConfigureAwait(false);

            if (responseMessage == null || responseMessage.StatusCode == HttpStatusCode.NoContent)
            {
                return(null);
            }

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.MessageId, out IEnumerable <string> messageId);
            responseMessage.Headers.TryGetValues(HttpResponseHeader.ETag.ToString(), out IEnumerable <string> lockToken);
            responseMessage.Headers.TryGetValues(CustomHeaderConstants.EnqueuedTime, out IEnumerable <string> enqueuedTime);
            responseMessage.Headers.TryGetValues(CustomHeaderConstants.DeliveryCount, out IEnumerable <string> deliveryCountAsStr);
            responseMessage.Headers.TryGetValues(CustomHeaderConstants.ExpiryTimeUtc, out IEnumerable <string> expiryTime);
            responseMessage.Headers.TryGetValues(CustomHeaderConstants.CorrelationId, out IEnumerable <string> correlationId);
            responseMessage.Headers.TryGetValues(CustomHeaderConstants.SequenceNumber, out IEnumerable <string> sequenceNumber);

            byte[] byteContent = await responseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);

            Message message = byteContent != null
                ? new Message(byteContent)
                : new Message();

            message.MessageId = messageId?.First();
            message.LockToken = lockToken?.First().Trim('\"');

            if (enqueuedTime != null)
            {
                if (DateTime.TryParse(enqueuedTime.First(), out DateTime enqueuedTimeUtc))
                {
                    message.EnqueuedTimeUtc = enqueuedTimeUtc;
                }
            }

            if (deliveryCountAsStr != null)
            {
                if (byte.TryParse(deliveryCountAsStr.First(), out byte deliveryCount))
                {
                    message.DeliveryCount = deliveryCount;
                }
            }

            if (expiryTime != null)
            {
                if (DateTime.TryParse(expiryTime.First(), out DateTime absoluteExpiryTime))
                {
                    message.ExpiryTimeUtc = absoluteExpiryTime;
                }
            }

            message.CorrelationId  = correlationId?.First();
            message.SequenceNumber = sequenceNumber == null
                ? 0
                : Convert.ToUInt64(sequenceNumber.First(), CultureInfo.InvariantCulture);

            // Read custom headers and map them to properties.
            foreach (KeyValuePair <string, IEnumerable <string> > keyValue in responseMessage.Headers)
            {
                if (keyValue.Key.StartsWith(CustomHeaderConstants.HttpAppPropertyPrefix, StringComparison.OrdinalIgnoreCase))
                {
                    message.Properties.Add(keyValue.Key.Substring(CustomHeaderConstants.HttpAppPropertyPrefix.Length), keyValue.Value.First());
                }
            }

            return(message);
        }
예제 #17
0
        protected async override Task <Message> OnReceiveAsync(TimeSpan timeout)
        {
            // Long-polling is not supported
            if (!TimeSpan.Zero.Equals(timeout))
            {
                throw new ArgumentOutOfRangeException("timeout", "Http Protocol does not support a non-zero receive timeout");
            }

            IDictionary <string, string> customHeaders        = PrepareCustomHeaders(CommonConstants.DeviceBoundPathTemplate.FormatInvariant(this.deviceId), null, CommonConstants.CloudToDeviceOperation);
            IDictionary <string, string> queryValueDictionary =
                new Dictionary <string, string>()
            {
                { CustomHeaderConstants.MessageLockTimeout, DefaultOperationTimeout.TotalSeconds.ToString(CultureInfo.InvariantCulture) }
            };

            var responseMessage = await this.httpClientHelper.GetAsync <HttpResponseMessage>(
                GetRequestUri(this.deviceId, CommonConstants.DeviceBoundPathTemplate, queryValueDictionary),
                ExceptionHandlingHelper.GetDefaultErrorMapping(),
                customHeaders,
                true,
                CancellationToken.None);

            if (responseMessage.StatusCode == HttpStatusCode.NoContent)
            {
                return(null);
            }

            IEnumerable <string> messageId;

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.MessageId, out messageId);

            IEnumerable <string> lockToken;

            responseMessage.Headers.TryGetValues(HttpResponseHeader.ETag.ToString(), out lockToken);

            IEnumerable <string> enqueuedTime;

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.EnqueuedTime, out enqueuedTime);

            IEnumerable <string> deliveryCountAsStr;

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.DeliveryCount, out deliveryCountAsStr);

            IEnumerable <string> expiryTime;

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.ExpiryTimeUtc, out expiryTime);

            IEnumerable <string> correlationId;

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.CorrelationId, out correlationId);

            IEnumerable <string> sequenceNumber;

            responseMessage.Headers.TryGetValues(CustomHeaderConstants.SequenceNumber, out sequenceNumber);

            var byteContent = await responseMessage.Content.ReadAsByteArrayAsync();

            var message = byteContent != null ? new Message(byteContent) : new Message();

            message.MessageId = messageId != null?messageId.First() : null;

            message.LockToken = lockToken != null?lockToken.First().Trim('\"') : null;

            if (enqueuedTime != null)
            {
                DateTime enqueuedTimeUtc;
                if (DateTime.TryParse(enqueuedTime.First(), out enqueuedTimeUtc))
                {
                    message.EnqueuedTimeUtc = enqueuedTimeUtc;
                }
            }

            if (deliveryCountAsStr != null)
            {
                byte deliveryCount;
                if (byte.TryParse(deliveryCountAsStr.First(), out deliveryCount))
                {
                    message.DeliveryCount = deliveryCount;
                }
            }

            if (expiryTime != null)
            {
                DateTime absoluteExpiryTime;
                if (DateTime.TryParse(expiryTime.First(), out absoluteExpiryTime))
                {
                    message.ExpiryTimeUtc = absoluteExpiryTime;
                }
            }

            message.CorrelationId = correlationId != null?correlationId.First() : null;

            message.SequenceNumber = sequenceNumber != null?Convert.ToUInt64(sequenceNumber.First()) : 0;


            return(message);
        }