2011-07-04 25 views
6

Realizo una solicitud a un servidor web remoto que actualmente no está en línea (a propósito).Cómo agotar el tiempo de espera de una solicitud utilizando Html Agility Pack

Me gustaría descubrir la mejor manera de finalizar la solicitud. Básicamente, si la solicitud se ejecuta durante más de "X" milisegundos, salga de la solicitud y devuelva una respuesta null.

Actualmente la solicitud Web sólo se sienta allí esperando una respuesta .....

¿cómo iba a mejor acercamiento a este problema?

Aquí está un fragmento de código de código actual

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

Respuesta

1

tuviera que hacer un pequeño ajuste a mi código publicado originalmente

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

Luego modifiqué mi RemoteFileExists extensio n método para tener un tiempo de espera

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

En este enfoque, si mis fuegos de tiempo de espera antes de RemoteFileExists pueden determinar la respuesta de encabezado, entonces mi bool devolverá falso.

0

Se puede usar un estándar HttpWebRequest para buscar el recurso remoto y establezca la propiedad Timeout. A continuación, ingrese el HTML resultante si tiene éxito en HTML Agility Pack para su análisis.

+0

¿Cuál sería la forma correcta de convertir un 'System.Net.WebRequest' en un' HtmlAgilityPack.HtmlDocument'? –

5

recuperar su página web URL a través de este método:

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

Y para usar el paquete de HTML agilidad y retrive la etiqueta html así:

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 Gracias por su respuesta, me ayudó a seguir el camino correcto. En lugar de leer el Html a través de 'HttpWebRequest', simplemente agregué un tiempo de espera a' RemoteFileExists' - [ver mi respuesta] (http://stackoverflow.com/questions/6574109/how-to-time-out-a-request- using-html-agility-pack/6574626 # 6574626) –

+3

@reggie: Solo una nota que una versión de producción de este código debería usar 'using' para cosas que son' IDisposable' como streams. –

5

Html Agility Pack is open souce. Es por eso que puedes modificar la fuente de ti mismo. Por primera añadir este código a la clase 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; 
     } 
    } 

luego encontrar este método

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

y modificarlo:

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

O algo así:

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

¡Eres genial! S –

Cuestiones relacionadas