/// <summary>
        /// A static method that routes errors to a single centralized error-handler.
        /// This method will attempt to extract a human-readable error from the response string,
        /// based on the the format of the data and the error handling scheme of the service.
        /// </summary>
        public static async Task ShowErrorMessageAsync(Office365ServiceInfo serviceInfo, string responseString)
        {
            string message, errorDetails;

            try
            {
                message      = serviceInfo.ParseErrorMessage(responseString);
                errorDetails = responseString;
            }
            catch (Exception e)
            {
                message      = "An unexpected error has occurred.";
                errorDetails = "Exception when parsing response string: " + e.ToString() +
                               "\n\nResponse string was " + responseString;
            }
            await ShowErrorMessageAsync(message, errorDetails);
        }
        /// <summary>
        /// Send an HTTP request, with authorization. If the request fails due to an unauthorized exception,
        ///     this method will try to renew the access token in serviceInfo and try again.
        /// </summary>
        public static async Task <HttpResponseMessage> SendRequestAsync(
            Office365ServiceInfo serviceInfo, HttpClient client, Func <HttpRequestMessage> requestCreator)
        {
            using (HttpRequestMessage request = requestCreator.Invoke())
            {
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", serviceInfo.AccessToken);
                request.Headers.UserAgent.Add(new ProductInfoHeaderValue((string)Application.Current.Resources["ida:ClientID"], String.Empty));
                HttpResponseMessage response = await client.SendAsync(request);

                // Check if the server responded with "Unauthorized". If so, it might be a real authorization issue, or
                //     it might be due to an expired access token. To be sure, renew the token and try one more time:
                if (response.StatusCode == HttpStatusCode.Unauthorized)
                {
                    string authority = string.Format(CultureInfo.InvariantCulture, OAuthUrl, TenantId ?? "common");
                    AuthenticationContext authContext = new AuthenticationContext(authority);

                    TokenCacheKey[] keysToRemove = (
                        from key in authContext.TokenCacheStore.Keys
                        where (key.Resource == serviceInfo.ResourceId) &&
                        (key.ClientId == (string)Application.Current.Resources["ida:ClientID"])
                        select key).ToArray();
                    foreach (TokenCacheKey key in keysToRemove)
                    {
                        authContext.TokenCacheStore.Remove(key);
                    }

                    serviceInfo.AccessToken = await GetAccessToken(serviceInfo.ResourceId);

                    // Create and send a new request:
                    using (HttpRequestMessage retryRequest = requestCreator.Invoke())
                    {
                        retryRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", serviceInfo.AccessToken);
                        retryRequest.Headers.UserAgent.Add(new ProductInfoHeaderValue((string)Application.Current.Resources["ida:ClientID"], String.Empty));
                        response = await client.SendAsync(retryRequest);
                    }
                }

                // Return either the original response, or the response from the second attempt:
                return(response);
            }
        }