web-dev-qa-db-fra.com

C # Comment puis-je vérifier si une URL existe/est valide?

Je crée un programme simple dans Visual C # 2005 qui recherche un symbole boursier sur Yahoo! Finance, télécharge les données historiques, puis trace l'historique des prix pour le symbole de ticker spécifié.

Je connais l'URL exacte dont j'ai besoin pour acquérir les données, et si l'utilisateur entre un symbole boursier existant (ou au moins un avec des données sur Yahoo! Finance), cela fonctionnera parfaitement. Cependant, j'ai une erreur d'exécution si l'utilisateur crée un symbole boursier, car le programme tente d'extraire des données d'une page Web inexistante.

J'utilise la classe WebClient et j'utilise la fonction DownloadString. J'ai parcouru toutes les autres fonctions membres de la classe WebClient, mais je n'ai rien vu que je puisse utiliser pour tester une URL.

Comment puis-je faire ceci?

103
Daniel Waltrip

Vous pourriez émettre un "HEAD" demande plutôt qu'un "GET"?

(edit) - lol! On dirait que j'ai fait ça avant !; changé en wiki pour éviter les accusations de rep-collecter. Donc, pour tester une URL sans le coût du téléchargement du contenu:

// using MyClient from linked post
using(var client = new MyClient()) {
    client.HeadOnly = true;
    // fine, no content downloaded
    string s1 = client.DownloadString("http://google.com");
    // throws 404
    string s2 = client.DownloadString("http://google.com/silly");
}

Vous devriez try/catch autour de DownloadString pour vérifier les erreurs; pas d'erreur? Ça existe...


Avec C # 2.0 (VS2005):

private bool headOnly;
public bool HeadOnly {
    get {return headOnly;}
    set {headOnly = value;}
}

et

using(WebClient client = new MyClient())
{
    // code as before
}
101
Marc Gravell

Voici une autre implémentation de cette solution:

using System.Net;

///
/// Checks the file exists or not.
///
/// The URL of the remote file.
/// True : If the file exits, False if file not exists
private bool RemoteFileExists(string url)
{
    try
    {
        //Creating the HttpWebRequest
        HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
        //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
        response.Close();
        return (response.StatusCode == HttpStatusCode.OK);
    }
    catch
    {
        //Any exception will returns false.
        return false;
    }
}

De: http://www.dotnet Thoughts.net/2009/10/10/how-to-check-remote-file-exists-using-c/

123
BigJoe714

Ces solutions sont plutôt bonnes, mais ils oublient qu'il peut y avoir d'autres codes d'état que 200 OK. C’est une solution que j’ai utilisée dans les environnements de production pour la surveillance de l’état, etc. 

S'il existe une redirection d'URL ou une autre condition sur la page cible, le retour sera true avec cette méthode. De plus, GetResponse () lève une exception et vous ne recevrez donc pas de StatusCode pour cela. Vous devez intercepter l'exception et rechercher une erreur ProtocolError.

Tout code de statut 400 ou 500 renverra faux. Tous les autres retournent vrai. Ce code est facilement modifiable en fonction de vos besoins pour des codes d’état spécifiques.

/// <summary>
/// This method will check a url to see that it does not return server or protocol errors
/// </summary>
/// <param name="url">The path to check</param>
/// <returns></returns>
public bool UrlIsValid(string url)
{
    try
    {
        HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest;
        request.Timeout = 5000; //set the timeout to 5 seconds to keep the user from waiting too long for the page to load
        request.Method = "HEAD"; //Get only the header information -- no need to download any content

        using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
        {
            int statusCode = (int)response.StatusCode;
            if (statusCode >= 100 && statusCode < 400) //Good requests
            {
                return true;
            }
            else if (statusCode >= 500 && statusCode <= 510) //Server Errors
            {
                //log.Warn(String.Format("The remote server has thrown an internal error. Url is not valid: {0}", url));
                Debug.WriteLine(String.Format("The remote server has thrown an internal error. Url is not valid: {0}", url));
                return false;
            }
        }
    }
    catch (WebException ex)
    {
        if (ex.Status == WebExceptionStatus.ProtocolError) //400 errors
        {
            return false;
        }
        else
        {
            log.Warn(String.Format("Unhandled status [{0}] returned for url: {1}", ex.Status, url), ex);
        }
    }
    catch (Exception ex)
    {
        log.Error(String.Format("Could not test url {0}.", url), ex);
    }
    return false;
}
31
jsmith

Si je comprends bien votre question, vous pouvez utiliser une petite méthode comme celle-ci pour vous donner les résultats de votre test d'URL:

WebRequest webRequest = WebRequest.Create(url);  
WebResponse webResponse;
try 
{
  webResponse = webRequest.GetResponse();
}
catch //If exception thrown then couldn't get response from address
{
  return 0;
} 
return 1;

Vous pouvez envelopper le code ci-dessus dans une méthode et l'utiliser pour effectuer une validation. J'espère que cela répond à la question que vous posiez.

8

Essayez ceci (assurez-vous d'utiliser System.Net):

public bool checkWebsite(string URL) {
   try {
      WebClient wc = new WebClient();
      string HTMLSource = wc.DownloadString(URL);
      return true;
   }
   catch (Exception) {
      return false;
   }
}

Lorsque la fonction checkWebsite () est appelée, elle tente d’obtenir le code source de L’URL qui y est passée. S'il obtient le code source, il renvoie true. Sinon, Il retourne faux.

Exemple de code:

//The checkWebsite command will return true:
bool websiteExists = this.checkWebsite("https://www.google.com");

//The checkWebsite command will return false:
bool websiteExists = this.checkWebsite("https://www.thisisnotarealwebsite.com/fakepage.html");
4
user6909992

Voici une autre option

public static bool UrlIsValid(string url)
{
    bool br = false;
    try {
        IPHostEntry ipHost = Dns.Resolve(url);
        br = true;
    }
    catch (SocketException se) {
        br = false;
    }
    return br;
}
2
Zain Ali

Cette solution semble facile à suivre:

public static bool isValidURL(string url) {
    WebRequest webRequest = WebRequest.Create(url);
    WebResponse webResponse;
    try
    {
        webResponse = webRequest.GetResponse();
    }
    catch //If exception thrown then couldn't get response from address
    {
        return false ;
    }
    return true ;
}
2
abobjects.com

j'ai un moyen plus simple de déterminer si une URL est valide.

if (Uri.IsWellFormedUriString(uriString, UriKind.RelativeOrAbsolute))
{
   //...
}
1
tsingroo

Les serveurs Web répondent avec un code d’état HTTP indiquant le résultat de la demande, par exemple. 200 (parfois 202) signifie succès, 404 - non trouvé, etc. (voir ici ). En supposant que l'adresse de serveur de l'URL soit correcte et que vous n'obtenez pas de délai d'expiration de socket, l'exception indique probablement que le code d'état HTTP était différent de 200. Je suggérerais de vérifier la classe de l'exception et de voir si l'exception le code de statut HTTP.

IIRC - L'appel en question lève une exception WebException ou un descendant. Vérifiez le nom de la classe pour voir lequel et enveloppez l'appel dans un bloc try pour intercepter la condition.

0
David Taylor

Pour reprendre les exemples déjà donnés, je dirais qu’il est préférable de placer également la réponse dans une utilisation telle que

    public bool IsValidUrl(string url)
    {
         try
         {
             var request = WebRequest.Create(url);
             request.Timeout = 5000;
             request.Method = "HEAD";

             using (var response = (HttpWebResponse)request.GetResponse())
             {
                response.Close();
                return response.StatusCode == HttpStatusCode.OK;
            }
        }
        catch (Exception exception)
        { 
            return false;
        }
   }
0
user3154431
WebRequest request = WebRequest.Create("http://www.google.com");
try
{
     request.GetResponse();
}
catch //If exception thrown then couldn't get response from address
{
     MessageBox.Show("The URL is incorrect");`
}
0
Praveen Dasare

J'ai toujours trouvé que les exceptions sont beaucoup plus lentes à traiter.

Peut-être une méthode moins intensive permettrait-elle d'obtenir un meilleur résultat plus rapidement?

public bool IsValidUri(Uri uri)
{

    using (HttpClient Client = new HttpClient())
    {

    HttpResponseMessage result = Client.GetAsync(uri).Result;
    HttpStatusCode StatusCode = result.StatusCode;

    switch (StatusCode)
    {

        case HttpStatusCode.Accepted:
            return true;
        case HttpStatusCode.OK:
            return true;
         default:
            return false;
        }
    }
}

Ensuite, utilisez simplement:

IsValidUri(new Uri("http://www.google.com/censorship_algorithm"));
0
Rusty Nail