web-dev-qa-db-fra.com

Une meilleure façon de valider l'URL en C # que d'essayer d'attraper?

Je crée une application pour récupérer une image sur Internet. Même si cela fonctionne bien, il est lent (sur une URL donnée incorrecte) lors de l'utilisation d'instructions try-catch dans l'application.

(1) Est-ce la meilleure façon de vérifier l'URL et de gérer une entrée incorrecte - ou devrais-je plutôt utiliser Regex (ou une autre méthode)?

(2) Pourquoi l'application essaie-t-elle de trouver des images localement si je ne spécifie pas http: // dans la zone de texte?

private void btnGetImage_Click(object sender, EventArgs e)
{
    String url = tbxImageURL.Text;
    byte[] imageData = new byte[1];

    using (WebClient client = new WebClient())
    {
        try
        {
            imageData = client.DownloadData(url);
            using (MemoryStream ms = new MemoryStream(imageData))
            {
                try
                {
                    Image image = Image.FromStream(ms);
                    pbxUrlImage.Image = image;
                }
                catch (ArgumentException)
                {
                    MessageBox.Show("Specified image URL had no match", 
                        "Image Not Found", MessageBoxButtons.OK, 
                        MessageBoxIcon.Error);
                }
            }
        }
        catch (ArgumentException)
        {
            MessageBox.Show("Image URL can not be an empty string", 
                "Empty Field", MessageBoxButtons.OK, 
                MessageBoxIcon.Information);
        }
        catch (WebException)
        {
            MessageBox.Show("Image URL is invalid.\nStart with http:// " +
                "and end with\na proper image extension", "Not a valid URL",
                MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    } // end of outer using statement
} // end of btnGetImage_Click

EDIT: J'ai essayé la solution suggérée par Panagiotis Kanavos (merci pour vos efforts!), Mais elle n'est prise dans l'instruction if-else que si l'utilisateur entre http:// Et rien de plus. Passer à UriKind.Absolute attrape également les chaînes vides! Se rapprocher :) Le code à partir de maintenant:

private void btnGetImage_Click(object sender, EventArgs e)
{
    String url = tbxImageURL.Text;
    byte[] imageData = new byte[1];
    Uri myUri;

    // changed to UriKind.Absolute to catch empty string
    if (Uri.TryCreate(url, UriKind.Absolute, out myUri))
    {
        using (WebClient client = new WebClient())
        {
            try
            {
                imageData = client.DownloadData(myUri);
                using (MemoryStream ms = new MemoryStream(imageData))
                {
                    imageData = client.DownloadData(myUri);
                    Image image = Image.FromStream(ms);
                    pbxUrlImage.Image = image;
                }
            }
            catch (ArgumentException)
            {
                MessageBox.Show("Specified image URL had no match",
                    "Image Not Found", MessageBoxButtons.OK, 
                    MessageBoxIcon.Error);
            }
            catch (WebException)
            {
                MessageBox.Show("Image URL is invalid.\nStart with http:// " +
                    "and end with\na proper image extension", 
                    "Not a valid URL",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
    }
    else
    {
        MessageBox.Show("The Image Uri is invalid.\nStart with http:// " +
            "and end with\na proper image extension", "Uri was not created",
            MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

Je dois faire quelque chose de mal ici. :(

63
Benny Skogberg

Utilisez ri.TryCreate pour créer un nouvel objet Uri uniquement si votre chaîne d'URL est une URL valide. Si la chaîne n'est pas une URL valide, TryCreate renvoie false.

string myString = "http://someUrl";
Uri myUri;
if (Uri.TryCreate(myString, UriKind.RelativeOrAbsolute, out myUri))
{
    //use the uri here
}

[~ # ~] mise à jour [~ # ~]

TryCreate ou le constructeur Uri acceptera volontiers les chaînes qui peuvent apparaître non valides, par exemple "Host: www.stackoverflow.com", "Host:% 20www.stackoverflow.com" ou "chrome: about". En fait, ce sont des URI parfaitement valides qui spécifient un schéma personnalisé au lieu de "http".

La documentation de la propriété ri.Scheme fournit plus d'exemples comme "Gopher:" (n'importe qui s'en souvient?), "News", "mailto", "uuid".

Une application peut s'enregistrer en tant que gestionnaire de protocole personnalisé comme décrit dans MSDN ou autre SO questions, par exemple Comment enregistrer un protocole URL personnalisé dans Windows?

TryCreate ne fournit pas un moyen de se limiter à des schémas spécifiques. Le code doit vérifier la propriété Uri.Scheme pour s'assurer qu'elle contient une valeur acceptable

MISE À JOUR 2

Passer une chaîne bizarre comme "></script><script>alert(9)</script> renverra true et construira un objet Uri relatif. L'appel ri.IsWellFormedOriginalString retournera cependant faux. Vous devez donc probablement appeler IsWellFormedOriginalString si vous voulez vous assurer que les Uris relatifs sont bien formés.

D'un autre côté, appeler TryCreate avec UriKind.Absolute Retournera false dans ce cas.

Fait intéressant, Uri.IsWellFormedUriString appelle TryCreate en interne, puis renvoie la valeur de IsWellFormedOriginalString si un Uri relatif a été créé.

109
Panagiotis Kanavos

Un raccourci serait d'utiliser ri.IsWellFormedUriString :

if (Uri.IsWellFormedUriString(myURL, UriKind.RelativeOrAbsolute))
...
53
Todd Menier

Certains exemples lors de l'utilisation d'Uri pour tester une URL valide échouent

Uri myUri = null;
if (Uri.TryCreate("Host: www.stackoverflow.com", UriKind.Absolute, out myUri))
{
}

  myUri = null;
if (Uri.TryCreate("Accept: application/json, text/javascript, */*; q=0.01", UriKind.Absolute, out myUri))
{
}

  myUri = null;
if (Uri.TryCreate("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0", UriKind.Absolute, out myUri))
{
}

  myUri = null;
if (Uri.TryCreate("DNT: 1", UriKind.Absolute, out myUri))
{
}

J'ai été surpris de voir toutes ces bêtises apparaître dans ma liste après avoir validé avec ce qui précède. Mais tout passe le test de validation.

Maintenant, j'ajoute ce qui suit après la validation ci-dessus

url = url.ToLower();
if (url.StartsWith("http://") || url.StartsWith("https://")) return true;
5
Martin

Salut, vous validez https http, ftp, sftp, ftps, tout ce qui commence par www.

string regular = @"^(ht|f|sf)tp(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$";
string regular123 = @"^(www.)[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$";

string myString = textBox1.Text.Trim();
if (Regex.IsMatch(myString, regular))
{
    MessageBox.Show("It is valide url  " + myString);
}
else if (Regex.IsMatch(myString, regular123))
{
    MessageBox.Show("Valide url with www. " + myString);
}
else 
{
    MessageBox.Show("InValide URL  " + myString);
}
4
Naren

Utilise le.....

string myString = http//:google.com;
Uri myUri;
Uri.TryCreate(myString, UriKind.RelativeOrAbsolute, out myUri);
 if (myUri.IsAbsoluteUri == false)
 {
  MessageBox.Show("Please Input Valid Feed Url");
 }
3
Shivam Srivastava

Ou ce code source bonne optimisation valide de l'image:

 public static string ValidateImage(string absoluteUrl,string defaultUrl)
        { 
           Uri myUri=null; 
           if (Uri.TryCreate(absoluteUrl, UriKind.Absolute, out myUri))
            {
                using (WebClient client = new WebClient())
                {
                    try
                    {
                        using (Stream stream = client.OpenRead(myUri))
                        {
                            Image image = Image.FromStream(stream);
                            return (image != null) ? absoluteUrl : defaultUrl;
                        }
                    }
                    catch (ArgumentException)
                    {
                        return defaultUrl;
                    }
                    catch (WebException)
                    {
                        return defaultUrl;
                    }
                }
            }
            else
            {
                return defaultUrl;
            }
        }

Sou et démo asp.net mvc image source créée:

<img src="@ValidateImage("http://example.com/demo.jpg","nophoto.png")"/>
3
Elyor

Ma solution:

string regular = @"^(ht|f|sf)tp(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$";
string myString = textBox1.Text.Trim();
if (Regex.IsMatch(myString, regular))
{
    MessageBox.Show("it is valide url  " + myString);
}
else
{
    MessageBox.Show("InValide url  " + myString);
}
3
Naren

vous pouvez utiliser la fonction Uri.TryCreate Comme Panagiotis Kanavos suggéré si vous souhaitez tester et créer une URL ou vous pouvez utiliser Uri.IsWellFormedUriString fonctionne comme suggéré par Todd Menier si vous vouliez juste tester la validité de l'URL. cela peut être pratique si vous validez simplement l'entrée utilisateur pour l'instant et devez créer l'url plus tard dans la durée de vie de votre application.

** Mais mon message est pour le peuple, comme moi :(, toujours en train de se frapper la tête contre .net 1.1 **

les deux méthodes ci-dessus ont été introduites dans .net 2.0, vous devez donc toujours utiliser la méthode try catch, qui, à mon avis, est bien meilleure que l'utilisation de l'expression régulière.

private bool IsValidHTTPURL(string url)
{
    bool result = false;

    try
    {
        Uri uri = new Uri(url);

        result = (uri.Scheme == "http" || uri.Scheme == "https");
    }
    catch (Exception ex) 
    { 
        log.Error("Exception while validating url", ex); 
    }

    return result;
}
2
Mubashar

Je voulais vérifier si l'URL contient également une extension de domaine, il doit s'agir d'une URL de site Web valide.

Voici ce que j'ai trouvé:

 public static bool IsValidUrl(string url)
        {
            if (string.IsNullOrEmpty(url)) { return false;}

            if (!url.StartsWith("http://"))
            {
                url = "http://" + url;    
            }

            Uri outWebsite;

            return Uri.TryCreate(url, UriKind.Absolute, out outWebsite) && outWebsite.Host.Replace("www.", "").Split('.').Count() > 1 && outWebsite.HostNameType == UriHostNameType.Dns && outWebsite.Host.Length > outWebsite.Host.LastIndexOf(".") + 1 && 255 >= url.Length;
        }

J'ai testé le code avec linqpad:

    void Main()
{
        // Errors
        IsValidUrl("www.google/cookie.png").Dump();
        IsValidUrl("1234").Dump();
        IsValidUrl("abcdef").Dump();
        IsValidUrl("abcdef/test.png").Dump();
        IsValidUrl("www.org").Dump();
        IsValidUrl("google").Dump();
        IsValidUrl("google.").Dump();
        IsValidUrl("google/test").Dump();
        IsValidUrl("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0").Dump();
        IsValidUrl("</script><script>alert(9)</script>").Dump();
        IsValidUrl("Accept: application/json, text/javascript, */*; q=0.01").Dump();
        IsValidUrl("DNT: 1").Dump();

        Environment.NewLine.Dump();

        // Success
        IsValidUrl("google.nl").Dump();
        IsValidUrl("www.google.nl").Dump();
        IsValidUrl("http://google.nl").Dump();
        IsValidUrl("http://www.google.nl").Dump();
}

Résultats:

Faux Faux Faux Faux Faux Faux Faux Faux Faux Faux Faux Faux Faux

Vrai Vrai Vrai Vrai

2
Jamie