/// <summary>
        /// Requests the remote HTML.
        /// </summary>
        /// <param name="cacheProvider">Strategy for caching the remote HTML.</param>
        /// <param name="selectedSection">The selected section.</param>
        private void RequestRemoteHtml(RemoteMasterPageCacheProviderBase cacheProvider, string selectedSection)
        {
            try
            {
                // Get the URL to request the cached control from.
                // Include text size so that header knows which links to apply
                var textSize        = new TextSize(HttpContext.Current.Request.Cookies, HttpContext.Current.Request.QueryString);
                Uri urlToRequest    = new Uri(HttpContext.Current.Request.Url, String.Format(CultureInfo.CurrentCulture, config["MasterPageControlUrl"], this.Control));
                var applicationPath = HttpUtility.UrlEncode(HttpRuntime.AppDomainAppVirtualPath.ToLower(CultureInfo.CurrentCulture).TrimEnd('/'));
                var query           = HttpUtility.ParseQueryString(urlToRequest.Query);
                query.Add("section", selectedSection);
                query.Add("host", Page.Request.Url.Host);
                query.Add("textsize", textSize.CurrentTextSize().ToString(CultureInfo.InvariantCulture));
                query.Add("path", applicationPath);
                urlToRequest = new Uri(urlToRequest.Scheme + "://" + urlToRequest.Authority + urlToRequest.AbsolutePath + "?" + query);

                // Create the request. Pass current user-agent so that library catalogue PCs can be detected by the remote script.
                var webRequest = (HttpWebRequest)WebRequest.Create(urlToRequest);
                webRequest.UseDefaultCredentials = true;
                webRequest.UserAgent             = Page.Request.UserAgent;
                webRequest.Proxy   = new ConfigurationProxyProvider().CreateProxy();
                webRequest.Timeout = 4000;
                if (!String.IsNullOrEmpty(this.config["Timeout"]))
                {
                    int timeout;
                    if (Int32.TryParse(this.config["Timeout"], out timeout))
                    {
                        webRequest.Timeout = timeout;
                    }
                }
#if DEBUG
                // Turn off SSL check in debug mode as it will always fail against a self-signed certificate used for development
                webRequest.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
#endif

                // Prepare the information we'll need when the response comes back
                var state = new RequestState();
                state.Request       = webRequest;
                state.CacheProvider = cacheProvider;

                // Kick off the request and, only if there's nothing already cached which we can use, wait for it to come back
                if (cacheProvider.SupportsAsync)
                {
                    RequestRemoteHtmlAsynchronous(cacheProvider, webRequest, state);
                }
                else
                {
                    RequestRemoteHtmlSynchronous(cacheProvider, webRequest);
                }
            }
            catch (UriFormatException ex)
            {
                throw new ConfigurationErrorsException(String.Format(CultureInfo.CurrentCulture, config["MasterPageControlUrl"], this.Control) + " is not a valid absolute URL", ex);
            }
        }
 private static void RequestRemoteHtmlSynchronous(RemoteMasterPageCacheProviderBase cacheProvider, HttpWebRequest webRequest)
 {
     try
     {
         using (var response = webRequest.GetResponse())
         {
             using (var responseStream = response.GetResponseStream())
             {
                 cacheProvider.SaveRemoteHtmlToCache(responseStream);
             }
         }
     }
     catch (WebException ex)
     {
         // Publish exception, otherwise it just disappears as async method has no calling code to throw to.
         ex.Data.Add("URL which failed", webRequest.RequestUri);
         ex.ToExceptionless().Submit();
     }
 }
        private void RequestRemoteHtmlAsynchronous(RemoteMasterPageCacheProviderBase cacheProvider, HttpWebRequest webRequest, RequestState state)
        {
            // Only wait for the response if there's nothing there at all.
            // If there is a cached version use that, but set the update running in the background.
            if (!cacheProvider.CachedVersionExists)
            {
                if (waitFor == null)
                {
                    waitFor = new Dictionary <string, ManualResetEvent>();
                }
                waitFor[this.Control] = new ManualResetEvent(false);
                state.WaitForResponse = waitFor[this.Control];
            }

            webRequest.BeginGetResponse(new AsyncCallback(Response_Callback), state);
            if (!cacheProvider.CachedVersionExists)
            {
                waitFor[this.Control].WaitOne(new TimeSpan(0, 0, 10));
            }
        }