void DiscoverRsdOnPage(string webAPI, TextReader streamReader, TaskCompletionSource <DiscoveryResult> taskCompletionSource)
        {
            const string linkTagRegex = "(?<link>\\<link .*?type=\"application/rsd\\+xml\".*?/\\>)";

            var response     = streamReader.ReadToEnd();
            var link         = Regex.Match(response, linkTagRegex, RegexOptions.IgnoreCase);
            var rsdLinkMatch = link.Groups["link"];

            if (!rsdLinkMatch.Success)
            {
                taskCompletionSource.SetResult(DiscoveryResult.Failed("Unable to resolve link to rsd file from url"));
                return;
            }

            var rsdLocationMatch = Regex.Match(rsdLinkMatch.Value, "href=(?:\"|')(?<link>.*?)(?:\"|')");

            if (!rsdLocationMatch.Groups["link"].Success)
            {
                taskCompletionSource.SetResult(DiscoveryResult.Failed("Unable to parse rsd link tag"));
                return;
            }

            var rsdUri = new Uri(rsdLocationMatch.Groups["link"].Value, UriKind.RelativeOrAbsolute);

            if (!rsdUri.IsAbsoluteUri)
            {
                rsdUri = new Uri(new Uri(webAPI, UriKind.Absolute), rsdUri);
            }

            var rdsWebRequest     = webRequestFactory.Create(rsdUri);
            var rdsWebRequestTask = rdsWebRequest.GetResponseAsync();

            // Add a continuation that will only execute if the request succeeds and continues processing the RSD
            rdsWebRequestTask.ContinueWith(rdsWebRequestAntecedent =>
                                           taskCompletionSource.SetResult(ProcessRsdResponse(rdsWebRequestAntecedent)),
                                           TaskContinuationOptions.NotOnFaulted);

            // Add a continuation that will only execute if the request faults and propagates the exception via the TCS
            rdsWebRequestTask.ContinueWith(rdsWebRequestAntecdent =>
                                           taskCompletionSource.SetResult(new DiscoveryResult(rdsWebRequestAntecdent.Exception)),
                                           TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnFaulted);
        }
        static DiscoveryResult ProcessRsdResponse(Task <WebResponse> webResponseTask)
        {
            if (webResponseTask.IsFaulted)
            {
                return(new DiscoveryResult(webResponseTask.Exception));
            }

            try
            {
                using (var webResponse = webResponseTask.Result)
                {
                    using (var responseStream = webResponse.GetResponseStream())
                    {
                        var document   = XDocument.Load(responseStream);
                        var apiElement = GetMetaWebLogElement(document);
                        if (apiElement == null)
                        {
                            return(DiscoveryResult.Failed("Unable to get metaweblog api address from rds.xml"));
                        }

                        var xAttribute = apiElement.Attribute("apiLink");
                        if (xAttribute == null)
                        {
                            return(DiscoveryResult.Failed("apiLink attribute not present for metaweblog api reference"));
                        }

                        var webApiLink = xAttribute.Value;
                        return(new DiscoveryResult(webApiLink));
                    }
                }
            }
            catch (Exception ex)
            {
                return(new DiscoveryResult(ex));
            }
        }