Search code examples
c#.netasp.net-mvc-3timeouthtml-agility-pack

How to Timeout a request using Html Agility Pack


I'm making a request to a remote web server that is currently offline (on purpose).

I'd like to figure out the best way to time out the request. Basically if the request runs longer than "X" milliseconds, then exit the request and return a null response.

Currently the web request just sits there waiting for a response.....

How would I best approach this problem?

Here's a current code snippet

    public JsonpResult About(string HomePageUrl)
    {
        Models.Pocos.About about = null;
        if (HomePageUrl.RemoteFileExists())
        {
            // Using the Html Agility Pack, we want to extract only the
            // appropriate data from the remote page.
            HtmlWeb hw = new HtmlWeb();
            HtmlDocument doc = hw.Load(HomePageUrl);
            HtmlNode node = doc.DocumentNode.SelectSingleNode("//div[@class='wrapper1-border']");

            if (node != null)
            { 
                about = new Models.Pocos.About { html = node.InnerHtml };
            }
                //todo: look into whether this else statement is necessary
            else 
            {
                about = null;
            }
        }

        return this.Jsonp(about);
    }

Solution

  • I had to make a small adjustment to my originally posted code

        public JsonpResult About(string HomePageUrl)
        {
            Models.Pocos.About about = null;
            // ************* CHANGE HERE - added "timeout in milliseconds" to RemoteFileExists extension method.
            if (HomePageUrl.RemoteFileExists(1000))
            {
                // Using the Html Agility Pack, we want to extract only the
                // appropriate data from the remote page.
                HtmlWeb hw = new HtmlWeb();
                HtmlDocument doc = hw.Load(HomePageUrl);
                HtmlNode node = doc.DocumentNode.SelectSingleNode("//div[@class='wrapper1-border']");
    
                if (node != null)
                { 
                    about = new Models.Pocos.About { html = node.InnerHtml };
                }
                    //todo: look into whether this else statement is necessary
                else 
                {
                    about = null;
                }
            }
    
            return this.Jsonp(about);
        }
    

    Then I modified my RemoteFileExists extension method to have a timeout

        public static bool RemoteFileExists(this string url, int timeout)
        {
            try
            {
                //Creating the HttpWebRequest
                HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
    
                // ************ ADDED HERE
                // timeout the request after x milliseconds
                request.Timeout = timeout;
                // ************
    
                //Setting the Request method HEAD, you can also use GET too.
                request.Method = "HEAD";
                //Getting the Web Response.
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                //Returns TRUE if the Status code == 200
                return (response.StatusCode == HttpStatusCode.OK);
            }
            catch
            {
                //Any exception will returns false.
                return false;
            }
        }
    

    In this approach, if my timeout fires before RemoteFileExists can determine the header response, then my bool will return false.