예제 #1
0
        public void OnActionExecuted(ActionExecutedContext context)
        {
            if (context.Exception is ValidationException exception)
            {
                //var responseContent = new HttpValidationErrorResponse
                //{
                //    FieldName = exception.
                //};

                //context.Result = new ObjectResult(responseContent)
                //{
                //    StatusCode = 403,
                //};
                //context.ExceptionHandled = true;
            }
            else
            {
                var responseContent = new HttpErrorResponse
                {
                    Message = context.Exception.Message
                };

                context.Result = new ObjectResult(responseContent)
                {
                    StatusCode = 400,
                };
                context.ExceptionHandled = true;
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DevicePortalException"/> class.
        /// </summary>
        /// <param name="statusCode">The Http status code.</param>
        /// <param name="errorResponse">Http parsed error response message.</param>
        /// <param name="requestUri">Request URI which threw the exception.</param>
        /// <param name="message">Optional exception message.</param>
        /// <param name="innerException">Optional inner exception.</param>
        public DevicePortalException(
            HttpStatusCode statusCode,
            HttpErrorResponse errorResponse,
            Uri requestUri           = null,
            string message           = "",
            Exception innerException = null) : this(
                statusCode,
                errorResponse.Reason,
                requestUri,
                message,
                innerException)
        {
            this.HResult = errorResponse.ErrorCode;
            this.Reason  = errorResponse.ErrorMessage;

            // If we didn't get the Hresult and reason from these properties, try the other ones.
            if (this.HResult == 0)
            {
                this.HResult = errorResponse.Code;
            }

            if (string.IsNullOrEmpty(this.Reason))
            {
                this.Reason = errorResponse.Reason;
            }
        }
예제 #3
0
        //TODO remove a the logMessage set, logger service might be a good candidate
        /// <summary>
        /// Handles all exceptions in application
        /// </summary>
        /// <param name="context">The HttpContext for the request</param>
        /// <param name="exception">The exception that was thrown</param>
        /// <returns></returns>
        private Task HandleExceptionAsync(HttpContext context, Exception exception)
        {
            _trackingService.AddTrackingIdToContext(context);
            var logMessage = "An unhandled exception has occurred: " + exception.Message;
            var code       = (int)HttpStatusCode.InternalServerError;

            var result = HttpErrorResponse.GetHttpErrorResponse(exception);

            if (exception is ReplayDomainException)
            {
                logMessage = "A replay domain validation exception has occurred: " + exception.Message;
                code       = DomainException.HttpErrorCode;
            }
            else if (exception is DomainException)
            {
                logMessage = "A domain validation exception has occurred: " + exception.Message;
                code       = DomainException.HttpErrorCode;
            }

            _logger.LogError(exception, logMessage);

            context.Response.ContentType = "application/json";
            context.Response.StatusCode  = code;

            return(context.Response.WriteAsync(result));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DevicePortalException"/> class.
        /// </summary>
        /// <param name="responseMessage">Http response message.</param>
        /// <param name="message">Optional exception message.</param>
        /// <param name="innerException">Optional inner exception.</param>
        /// <returns>async task</returns>
        public static async Task <DevicePortalException> CreateAsync(
            HttpResponseMessage responseMessage,
            string message           = "",
            Exception innerException = null)
        {
            DevicePortalException error = new DevicePortalException(
                responseMessage.StatusCode,
                responseMessage.ReasonPhrase,
                responseMessage.RequestMessage != null ? responseMessage.RequestMessage.RequestUri : null,
                message,
                innerException);

            try
            {
                if (responseMessage.Content != null)
                {
                    Stream dataStream = null;
                    using (HttpContent content = responseMessage.Content)
                    {
                        dataStream = new MemoryStream();

                        await content.CopyToAsync(dataStream).ConfigureAwait(false);

                        // Ensure we point the stream at the origin.
                        dataStream.Position = 0;
                    }

                    if (dataStream != null)
                    {
                        HttpErrorResponse errorResponse = dataStream.ReadJson <HttpErrorResponse>();

                        if (errorResponse != null)
                        {
                            error.HResult = errorResponse.ErrorCode;
                            error.Reason  = errorResponse.ErrorMessage;

                            // If we didn't get the Hresult and reason from these properties, try the other ones.
                            if (error.HResult == 0)
                            {
                                error.HResult = errorResponse.Code;
                            }

                            if (string.IsNullOrEmpty(error.Reason))
                            {
                                error.Reason = errorResponse.Reason;
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                // Do nothing if we fail to get additional error details from the response body.
            }

            return(error);
        }
예제 #5
0
        /// <summary>
        /// Handles all exceptions in application
        /// </summary>
        /// <param name="context">The HttpContext for the request</param>
        /// <param name="exception">The exception that was thrown</param>
        /// <returns></returns>
        private Task HandleExceptionAsync(HttpContext context, Exception exception, String requestBody)
        {
            var logMessage = "An unhandled exception has occurred: " + exception.Message;
            var code       = (int)HttpStatusCode.BadRequest;
            var logInfo    = false;

            var result = HttpErrorResponse.GetHttpErrorResponse(exception);

            if (exception is ReplayDomainException)
            {
                logMessage = "A replay domain validation exception has occurred: " + exception.Message;
                code       = DomainException.HttpErrorCode;
                logInfo    = true;
            }
            else if (exception is DomainException)
            {
                logMessage = "A domain validation exception has occurred: " + exception.Message;
                code       = DomainException.HttpErrorCode;
            }
            else if (exception is InvalidOperationException)
            {
                logMessage = "Authentication invalid: " + exception.Message;
                code       = (int)HttpStatusCode.Unauthorized;
            }

            // Custom exceptions with above IF..

            if (logInfo)
            {
                _logger.LogInformation(exception, logMessage,
                                       string.Format("Original Request: {0} {1}://{2}{3} {4}",
                                                     context.Request.Method,
                                                     context.Request.Scheme,
                                                     context.Request.Host,
                                                     context.Request.Path,
                                                     context.Request.QueryString),
                                       requestBody);
            }
            else
            {
                _logger.LogError(exception, logMessage,
                                 string.Format("Original Request: {0} {1}://{2}{3} {4}",
                                               context.Request.Method,
                                               context.Request.Scheme,
                                               context.Request.Host,
                                               context.Request.Path,
                                               context.Request.QueryString),
                                 requestBody);
            }

            context.Response.ContentType = "application/json";
            context.Response.StatusCode  = code;

            return(context.Response.WriteAsync(result));
        }
예제 #6
0
        public void GET_returns_ArgumentNullException()
        {
            var restClient = CreateRestClient();

            WebServiceException webEx    = null;
            HttpErrorResponse   response = null;

            restClient.GetAsync <HttpErrorResponse>(ListeningOn + "errors",
                                                    r => response = r,
                                                    (r, ex) => {
                response = r;
                webEx    = (WebServiceException)ex;
            });

            Thread.Sleep(1000);

            Assert.That(webEx.StatusCode, Is.EqualTo(400));
            Assert.That(response.ResponseStatus.ErrorCode, Is.EqualTo(typeof(ArgumentNullException).Name));
        }
예제 #7
0
        public void GET_returns_custom_Exception_and_StatusCode()
        {
            var restClient = CreateRestClient();

            WebServiceException webEx    = null;
            HttpErrorResponse   response = null;

            restClient.GetAsync <HttpErrorResponse>(ListeningOn + "errors/FileNotFoundException/404",
                                                    r => response = r,
                                                    (r, ex) =>
            {
                response = r;
                webEx    = (WebServiceException)ex;
            });

            Thread.Sleep(1000);

            Assert.That(webEx.StatusCode, Is.EqualTo(404));
            Assert.That(response.ResponseStatus.ErrorCode, Is.EqualTo(typeof(FileNotFoundException).Name));
        }
예제 #8
0
        protected void Application_Error(object sender, EventArgs e)
        {
            var app = sender as HttpApplication;

            if (app == null)
            {
                return;
            }

            HttpErrorResponse httpError = null;

            try
            {
                var exception = app.Server.GetLastError();
                //Logger.ErrorFormat("Caught unhandled exception in http module: {0}.", exception);
                httpError = ErrorMessageHandler.CreateResponseFromException(exception);
            }
            catch (Exception ex)
            {
                //Logger.ErrorFormat("Error occurred when handling exception: {0}", ex);
                httpError = new HttpErrorResponse
                {
                    HttpStatusCode = HttpStatusCode.InternalServerError,
                    ErrorOutput    = new ErrorResponse(new Error
                    {
                        Code    = ErrorCode.InternalServerError,
                        Message = ErrorMessage.InternalServerError
                    })
                };
            }

            var response = app.Context.Response;

            response.TrySkipIisCustomErrors = true;

            // Ensure ASP.NET not to show 'Yellow Screen of Death'.
            app.Server.ClearError();

            #region 创建返回类

            // Ensure that any content written to the response stream is erased.
            response.Clear();
            response.ClearContent();

            response.StatusCode  = (int)httpError.HttpStatusCode;
            response.ContentType = "application/json; charset=utf-8";

            if (httpError.Headers != null)
            {
                foreach (var key in httpError.Headers.AllKeys)
                {
                    response.AddHeader(key, httpError.Headers.Get(key));
                }
            }
            #endregion

            string responseString = httpError.ErrorOutput.ToJsonDefault();
            response.Output.Write(responseString);

            response.Flush();

            app.Context.ApplicationInstance.CompleteRequest();
        }
예제 #9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DevicePortalException"/> class.
        /// </summary>
        /// <param name="responseMessage">Http response message.</param>
        /// <param name="message">Optional exception message.</param>
        /// <param name="innerException">Optional inner exception.</param>
        public DevicePortalException(
            HttpResponseMessage responseMessage,
            string message           = "",
            Exception innerException = null) : this(
                responseMessage.StatusCode,
                responseMessage.ReasonPhrase,
                responseMessage.RequestMessage != null ? responseMessage.RequestMessage.RequestUri : null,
                message,
                innerException)
        {
            try
            {
                if (responseMessage.Content != null)
                {
                    Stream dataStream = null;
#if !WINDOWS_UWP
                    using (HttpContent content = responseMessage.Content)
                    {
                        dataStream = new MemoryStream();

                        Task copyTask = content.CopyToAsync(dataStream);
                        copyTask.ConfigureAwait(false);
                        copyTask.Wait();

                        // Ensure we point the stream at the origin.
                        dataStream.Position = 0;
                    }
#else // WINDOWS_UWP
                    IBuffer dataBuffer = null;
                    using (IHttpContent messageContent = responseMessage.Content)
                    {
                        IAsyncOperationWithProgress <IBuffer, ulong> bufferOperation = messageContent.ReadAsBufferAsync();
                        while (bufferOperation.Status != AsyncStatus.Completed)
                        {
                        }

                        dataBuffer = bufferOperation.GetResults();

                        if (dataBuffer != null)
                        {
                            dataStream = dataBuffer.AsStream();
                        }
                    }
#endif  // WINDOWS_UWP

                    if (dataStream != null)
                    {
                        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HttpErrorResponse));

                        HttpErrorResponse errorResponse = (HttpErrorResponse)serializer.ReadObject(dataStream);

                        this.HResult = errorResponse.ErrorCode;
                        this.Reason  = errorResponse.ErrorMessage;

                        // If we didn't get the Hresult and reason from these properties, try the other ones.
                        if (this.HResult == 0)
                        {
                            this.HResult = errorResponse.Code;
                        }

                        if (string.IsNullOrEmpty(this.Reason))
                        {
                            this.Reason = errorResponse.Reason;
                        }
                    }
                }
            }
            catch (Exception)
            {
                // Do nothing if we fail to get additional error details from the response body.
            }
        }
        /// <summary>
        /// API for getting installation status.
        /// </summary>
        /// <returns>The status</returns>
#pragma warning disable 1998
        public async Task <ApplicationInstallStatus> GetInstallStatusAsync()
        {
            ApplicationInstallStatus status = ApplicationInstallStatus.None;

            Uri uri = Utilities.BuildEndpoint(
                this.deviceConnection.Connection,
                InstallStateApi);

            HttpBaseProtocolFilter httpFilter = new HttpBaseProtocolFilter();

            httpFilter.AllowUI = false;

            if (this.deviceConnection.Credentials != null)
            {
                httpFilter.ServerCredential          = new PasswordCredential();
                httpFilter.ServerCredential.UserName = this.deviceConnection.Credentials.UserName;
                httpFilter.ServerCredential.Password = this.deviceConnection.Credentials.Password;
            }

            using (HttpClient client = new HttpClient(httpFilter))
            {
                this.ApplyHttpHeaders(client, HttpMethods.Get);

                using (HttpResponseMessage response = await client.GetAsync(uri))
                {
                    if (response.IsSuccessStatusCode)
                    {
                        if (response.StatusCode == HttpStatusCode.Ok)
                        {
                            // Status code: 200
                            if (response.Content != null)
                            {
                                Stream dataStream = null;

                                IBuffer dataBuffer = null;
                                using (IHttpContent messageContent = response.Content)
                                {
                                    dataBuffer = await messageContent.ReadAsBufferAsync();

                                    if (dataBuffer != null)
                                    {
                                        dataStream = dataBuffer.AsStream();
                                    }
                                }

                                if (dataStream != null)
                                {
                                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HttpErrorResponse));

                                    HttpErrorResponse errorResponse = (HttpErrorResponse)serializer.ReadObject(dataStream);

                                    if (errorResponse.Success)
                                    {
                                        status = ApplicationInstallStatus.Completed;
                                    }
                                    else
                                    {
                                        throw new DevicePortalException(response.StatusCode, errorResponse, uri);
                                    }
                                }
                                else
                                {
                                    throw new DevicePortalException(HttpStatusCode.Conflict, "Failed to deserialize GetInstallStatus response.");
                                }
                            }
                        }
                        else if (response.StatusCode == HttpStatusCode.NoContent)
                        {
                            // Status code: 204
                            status = ApplicationInstallStatus.InProgress;
                        }
                    }
                    else
                    {
                        throw await DevicePortalException.CreateAsync(response);
                    }
                }
            }

            return(status);
        }
        /// <summary>
        /// API for getting installation status.
        /// </summary>
        /// <returns>The status</returns>
        public async Task <ApplicationInstallStatus> GetInstallStatus()
        {
            ApplicationInstallStatus status = ApplicationInstallStatus.None;

            Uri uri = Utilities.BuildEndpoint(
                this.deviceConnection.Connection,
                InstallStateApi);

            WebRequestHandler handler = new WebRequestHandler();

            handler.UseDefaultCredentials = false;
            handler.Credentials           = this.deviceConnection.Credentials;
            handler.ServerCertificateValidationCallback = this.ServerCertificateValidation;

            using (HttpClient client = new HttpClient(handler))
            {
                this.ApplyHttpHeaders(client, HttpMethods.Get);

                Task <HttpResponseMessage> getTask = client.GetAsync(uri);
                await getTask.ConfigureAwait(false);

                getTask.Wait();

                using (HttpResponseMessage response = getTask.Result)
                {
                    if (response.IsSuccessStatusCode)
                    {
                        if (response.StatusCode == HttpStatusCode.OK)
                        {
                            // Status code: 200
                            if (response.Content == null)
                            {
                                status = ApplicationInstallStatus.Completed;
                            }
                            else
                            {
                                // If we have a response body, it's possible this was an error
                                // (even though we got an HTTP 200).
                                Stream dataStream = null;
                                using (HttpContent content = response.Content)
                                {
                                    dataStream = new MemoryStream();

                                    Task copyTask = content.CopyToAsync(dataStream);
                                    await copyTask.ConfigureAwait(false);

                                    copyTask.Wait();

                                    // Ensure we point the stream at the origin.
                                    dataStream.Position = 0;
                                }

                                if (dataStream != null)
                                {
                                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HttpErrorResponse));

                                    HttpErrorResponse errorResponse = (HttpErrorResponse)serializer.ReadObject(dataStream);

                                    if (errorResponse.Success)
                                    {
                                        status = ApplicationInstallStatus.Completed;
                                    }
                                    else
                                    {
                                        throw new DevicePortalException(response.StatusCode, errorResponse, uri);
                                    }
                                }
                                else
                                {
                                    throw new DevicePortalException(response.StatusCode, "Failed to deserialize GetInstallStatus response.");
                                }
                            }
                        }
                        else if (response.StatusCode == HttpStatusCode.NoContent)
                        {
                            // Status code: 204
                            status = ApplicationInstallStatus.InProgress;
                        }
                    }
                    else
                    {
                        throw new DevicePortalException(response);
                    }
                }
            }

            return(status);
        }
예제 #12
0
        /// <summary>
        /// Actually gets a matching response from the mock data
        /// </summary>
        /// <param name="requestInfo"></param>
        /// <returns></returns>
        public HttpResponseInfo SendRequest(HttpRequestInfo requestInfo)
        {
            HttpResponseInfo  responseInfo         = null;
            string            currentRequestString = requestInfo.ToString();
            string            currentAlertId       = Utils.RegexFirstGroupValue(currentRequestString, ALERT_MATCH);
            TrafficServerMode currentMatchMode     = _matchMode;

            if (!String.IsNullOrEmpty(currentAlertId))             //override the redundancy tuning if we are trying to match a alert
            {
                currentMatchMode = TrafficServerMode.BrowserFriendly;
            }

            //parse the request variables because we will need them to construct the hash
            requestInfo.ParseVariables();


            TrafficServerResponseSet responseSet = null;

            //look in the server cache for the request
            ICacheable entry =
                TrafficServerCache.Instance.GetEntry(requestInfo.GetHashCode(currentMatchMode));


            if (entry != null)
            {
                responseSet = entry.Reserve() as TrafficServerResponseSet;
                entry.Release();
            }

            TrafficServerResponseSet similarRequests = new TrafficServerResponseSet();

            if (responseSet == null)
            {
                //create a new empty response set
                responseSet = new TrafficServerResponseSet();

                RequestSearcher searcher = new RequestSearcher();

                SearchCriteriaSet criteriaSet;

                criteriaSet = GetCriteriaSet(requestInfo, currentMatchMode);

                RequestMatches matches = new RequestMatches();

                //do the search!
                searcher.Search(_sourceStore, criteriaSet, matches);

                //normalize the matches and keep only the ones that have the same variables and values
                if (matches.Count > 0)
                {
                    HttpRequestInfo original;
                    HttpRequestInfo found;
                    byte[]          requestBytes;
                    int             i, n = matches.Count;
                    for (i = 0; i < n & i < MATCHES_LIMIT; i++)
                    {
                        int           match  = matches[i];
                        TVRequestInfo header = _sourceStore.GetRequestInfo(match);
                        if (_ignoreAuth)
                        {
                            if (
                                String.Compare(header.ResponseStatus, "401", true) == 0 ||
                                String.Compare(header.ResponseStatus, "407", true) == 0)
                            {
                                HttpServerConsole.Instance.WriteLine(LogMessageType.Warning, "Skipping authentication challenge");
                                //simply skip 401 matches
                                continue;
                            }
                        }

                        if (String.Compare(header.Description, Resources.TrafficLogProxyDescription, true) == 0)
                        {
                            //is likely that the source store is also the save store and this may be
                            //the current request being saved
                            HttpServerConsole.Instance.WriteLine(LogMessageType.Warning, "Skipping request to traffic store");
                            continue;
                        }


                        requestBytes = _sourceStore.LoadRequestData(match);
                        string requestString = Constants.DefaultEncoding.GetString(requestBytes);

                        if (String.IsNullOrEmpty(requestString))
                        {
                            continue;                             //skip the current match is incorrect
                        }
                        original = new HttpRequestInfo(DynamicElementsRemover.Remove(currentRequestString));
                        found    = new HttpRequestInfo(DynamicElementsRemover.Remove(requestString));

                        if (RequestMatcher.IsMatch(original, found, TrafficServerMode.Strict))
                        {
                            responseSet.Add(match);
                        }
                        else if (currentMatchMode != TrafficServerMode.Strict &&
                                 RequestMatcher.IsMatch(original, found, currentMatchMode))
                        {
                            similarRequests.Add(match);
                        }
                    }
                    //if no exact requests were found
                    if (responseSet.Count == 0 && similarRequests.Count > 0)
                    {
                        HttpServerConsole.Instance.WriteLine
                            (LogMessageType.Warning, "Warning, exact match was not found for {0} returning a similar request.",
                            requestInfo.RequestLine);
                    }
                    responseSet.AddRange(similarRequests.Matches);
                }

                //add this response set to the cache
                TrafficServerCache.Instance.Add(requestInfo.GetHashCode(currentMatchMode), new CacheEntry(responseSet));
            }

            //get the next response id from the response set
            int requestId = responseSet.GetNext();

            if (requestId == NULL_INDEX)
            {
                HttpServerConsole.Instance.WriteLine(LogMessageType.Warning, "(404) Request not found: {0}"
                                                     , requestInfo.RequestLine);
                //the request was not found at all, return a 404
                return(new HttpResponseInfo(HttpErrorResponse.GenerateHttpErrorResponse(HttpStatusCode.NotFound, "Request Not Found",
                                                                                        "<html><head><title>Error code: 404</title><body><h1>Request was not found or variables didn't match.</h1></body></html>")));
            }

            if (requestId != NULL_INDEX)
            {
                HttpServerConsole.Instance.WriteLine(LogMessageType.Information, "Returning response from request id: {0}", requestId);
                byte[] responseBytes = _sourceStore.LoadResponseData(requestId);

                if (responseBytes != null)
                {
                    responseInfo = new HttpResponseInfo(responseBytes);

                    if (!String.IsNullOrEmpty(currentAlertId))
                    {
                        Encoding encoding       = HttpUtil.GetEncoding(responseInfo.Headers["Content-Type"]);
                        string   responseString = encoding.GetString(responseBytes);
                        responseString = Utils.ReplaceGroups(responseString, ALERT_MATCH, currentAlertId);
                        responseInfo   = new HttpResponseInfo(encoding.GetBytes(responseString));
                    }
                }

                //add the request id header
                responseInfo.Headers.Add("Traffic-Store-Req-Id", requestId.ToString());
            }

            return(responseInfo);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DevicePortalException"/> class.
        /// </summary>
        /// <param name="responseMessage">Http response message.</param>
        /// <param name="message">Optional exception message.</param>
        /// <param name="innerException">Optional inner exception.</param>
        /// <returns>async task</returns>
        public static async Task <DevicePortalException> CreateAsync(
            HttpResponseMessage responseMessage,
            string message           = "",
            Exception innerException = null)
        {
            DevicePortalException error = new DevicePortalException(
                responseMessage.StatusCode,
                responseMessage.ReasonPhrase,
                responseMessage.RequestMessage != null ? responseMessage.RequestMessage.RequestUri : null,
                message,
                innerException);

            try
            {
                if (responseMessage.Content != null)
                {
                    Stream dataStream = null;
#if !WINDOWS_UWP
                    using (HttpContent content = responseMessage.Content)
                    {
                        dataStream = new MemoryStream();

                        await content.CopyToAsync(dataStream).ConfigureAwait(false);

                        // Ensure we point the stream at the origin.
                        dataStream.Position = 0;
                    }
#else // WINDOWS_UWP
                    IBuffer dataBuffer = null;
                    using (IHttpContent messageContent = responseMessage.Content)
                    {
                        dataBuffer = await messageContent.ReadAsBufferAsync();

                        if (dataBuffer != null)
                        {
                            dataStream = dataBuffer.AsStream();
                        }
                    }
#endif  // WINDOWS_UWP

                    if (dataStream != null)
                    {
                        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HttpErrorResponse));

                        HttpErrorResponse errorResponse = (HttpErrorResponse)serializer.ReadObject(dataStream);

                        error.HResult = errorResponse.ErrorCode;
                        error.Reason  = errorResponse.ErrorMessage;

                        // If we didn't get the Hresult and reason from these properties, try the other ones.
                        if (error.HResult == 0)
                        {
                            error.HResult = errorResponse.Code;
                        }

                        if (string.IsNullOrEmpty(error.Reason))
                        {
                            error.Reason = errorResponse.Reason;
                        }

                        dataStream.Dispose();
                    }
                }
            }
            catch (Exception)
            {
                // Do nothing if we fail to get additional error details from the response body.
            }

            return(error);
        }
예제 #14
0
        /// <summary>
        /// Gets the status of a pending or most recent installation, if any.
        /// </summary>
        /// <returns>The status</returns>
        public async Task <ApplicationInstallStatus> GetInstallStatusAsync()
        {
            ApplicationInstallStatus status = ApplicationInstallStatus.None;

            Uri uri = Utilities.BuildEndpoint(
                this.deviceConnection.Connection,
                InstallStateApi);

            using (HttpResponseMessage response = await this.HttpClient.GetAsync(uri).ConfigureAwait(false))
            {
                if (response.IsSuccessStatusCode)
                {
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        // Status code: 200
                        if (response.Content == null)
                        {
                            status = ApplicationInstallStatus.Completed;
                        }
                        else
                        {
                            // If we have a response body, it's possible this was an error
                            // (even though we got an HTTP 200).
                            Stream dataStream = null;
                            using (HttpContent content = response.Content)
                            {
                                dataStream = new MemoryStream();

                                await content.CopyToAsync(dataStream).ConfigureAwait(false);

                                // Ensure we point the stream at the origin.
                                dataStream.Position = 0;
                            }

                            if (dataStream != null)
                            {
                                DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HttpErrorResponse));

                                HttpErrorResponse errorResponse = (HttpErrorResponse)serializer.ReadObject(dataStream);

                                if (errorResponse.Success)
                                {
                                    status = ApplicationInstallStatus.Completed;
                                }
                                else
                                {
                                    throw new DevicePortalException(response.StatusCode, errorResponse, uri);
                                }
                            }
                            else
                            {
                                throw new DevicePortalException(response.StatusCode, "Failed to deserialize GetInstallStatus response.");
                            }
                        }
                    }
                    else if (response.StatusCode == HttpStatusCode.NoContent)
                    {
                        // Status code: 204
                        status = ApplicationInstallStatus.InProgress;
                    }
                }
                else
                {
                    throw await DevicePortalException.CreateAsync(response);
                }
            }

            return(status);
        }