2011-07-04 13 views
6

Wysyłam żądanie do zdalnego serwera WWW, który jest obecnie niedostępny (celowo).Jak ustawić limit czasu żądania za pomocą pakietu Agility Pack Html

Chciałbym znaleźć najlepszy sposób, aby przerwać żądanie. Zasadniczo, jeśli żądanie trwa dłużej niż "X" milisekund, zakończ żądanie i zwróć odpowiedź null.

Obecnie wniosek internetowej po prostu siedzi tam czeka na odpowiedź .....

jak bym najlepszym rozwiązaniem tego problemu?

Oto aktualny kod 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); 
    } 

Odpowiedz

1

musiałem zrobić małą korektę moja opublikowany pierwotnie kod

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); 
    } 

Potem zmodyfikowane mój RemoteFileExists extensio Metoda n mieć 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; 
     } 
    } 

W ramach tego podejścia, jeśli moje Timeout pożary przed RemoteFileExists można określić reakcję nagłówka, to mój bool zwróci false.

0

Można użyć standardu HttpWebRequest pobierać zdalnego zasobu i ustawić właściwość Timeout. Następnie podaj wynikowy kod HTML, jeśli uda mu się przetworzyć pakiet Agility HTML.

+0

jaki byłby właściwy sposób przekonwertowania 'System.Net.WebRequest' na' HtmlAgilityPack.HtmlDocument'? –

5

Odzyskaj swój adres URL strony internetowej za pośrednictwem tej metody:

private static string retrieveData(string url) 
    { 
     // used to build entire input 
     StringBuilder sb = new StringBuilder(); 

     // used on each read operation 
     byte[] buf = new byte[8192]; 

     // prepare the web page we will be asking for 
     HttpWebRequest request = (HttpWebRequest) 
     WebRequest.Create(url); 
     request.Timeout = 10; //10 millisecond 
     // execute the request 

     HttpWebResponse response = (HttpWebResponse) 
     request.GetResponse(); 

     // we will read data via the response stream 
     Stream resStream = response.GetResponseStream(); 

     string tempString = null; 
     int count = 0; 

     do 
     { 
      // fill the buffer with data 
      count = resStream.Read(buf, 0, buf.Length); 

      // make sure we read some data 
      if (count != 0) 
      { 
       // translate from bytes to ASCII text 
       tempString = Encoding.ASCII.GetString(buf, 0, count); 

       // continue building the string 
       sb.Append(tempString); 
      } 
     } 
     while (count > 0); // any more data to read? 

     return sb.ToString(); 
    } 

I używać pakiet HTML zwinność i sprowadzaniu tag HTML tak:

public static string htmlRetrieveInfo() 
    { 
     string htmlSource = retrieveData("http://example.com/test.html"); 
     HtmlDocument doc = new HtmlDocument(); 
     doc.LoadHtml(htmlSource); 
     if (doc.DocumentNode.SelectSingleNode("//body") != null) 
     { 
      HtmlNode node = doc.DocumentNode.SelectSingleNode("//body"); 
     } 
     return node.InnerHtml; 
    } 
+0

+1 Dziękuję za odpowiedź, doprowadził mnie do właściwej drogi. Zamiast czytać HTML przez 'HttpWebRequest', po prostu dodałem timeout do' RemoteFileExists' - [see my answer] (http://stackoverflow.com/questions/6574109/how-to-time-out-a-request- using-html-agility-pack/6574626 # 6574626) –

+3

@reggie: Tylko uwaga, że ​​wersja produkcyjna tego kodu powinna używać 'using' dla rzeczy, które są' IDisposable' jak strumienie. –

5

Pakiet Agility Pack Html to open souce. To dlatego możesz sam modyfikować źródło. Na pierwszy dodać ten kod do klasy HtmlWeb:

private int _timeout = 20000; 

public int Timeout 
    { 
     get { return _timeout; } 
     set 
     { 
      if (_timeout < 1) 
       throw new ArgumentException("Timeout must be greater then zero."); 
      _timeout = value; 
     } 
    } 

następnie znaleźć tę metodę

private HttpStatusCode Get(Uri uri, string method, string path, HtmlDocument doc, IWebProxy proxy, ICredentials creds) 

i modyfikowania go:

req = WebRequest.Create(uri) as HttpWebRequest; 
req.Method = method; 
req.UserAgent = UserAgent; 
req.Timeout = Timeout; //add this 

czy coś takiego:

htmlWeb.PreRequest = request => 
      { 
       request.Timeout = 15000; 
       return true; 
      }; 
+0

Jesteś świetny! –

Powiązane problemy