293 votes

Obtenir des paramètres d'URL à partir d'une chaîne de caractères en .NET

J'ai une chaîne dans .NET qui est en fait une URL. Je veux un moyen facile d'obtenir la valeur d'un paramètre particulier.

Normalement, j'aurais juste utilisé Request.Params["theThingIWant"] mais cette chaîne ne provient pas de la demande. Je peux créer un nouveau Uri comme ceci :

Uri myUri = new Uri(TheStringUrlIWantMyValueFrom);

Je peux utiliser myUri.Query pour obtenir la chaîne de requête... mais ensuite je dois apparemment trouver un moyen regexy de la diviser.

Est-ce que j'ai raté quelque chose d'évident, ou n'y a-t-il pas un moyen intégré de faire cela sans créer une sorte de regex, etc ?

581voto

CZFox Points 2938

Utiliser les statiques ParseQueryString méthode de System.Web.HttpUtility qui renvoie NameValueCollection .

Uri myUri = new Uri("http://www.example.com?param1=good&param2=bad");
string param1 = HttpUtility.ParseQueryString(myUri.Query).Get("param1");

Consultez la documentation à l'adresse suivante http://msdn.microsoft.com/en-us/library/ms150046.aspx

15 votes

Cela ne semble pas détecter le premier paramètre, par exemple en analysant " google.com/ "ne détecte pas le paramètre q

1 votes

@Andrew Je confirme. C'est étrange (bug ?). Vous pouvez toujours utiliser HttpUtility.ParseQueryString(myUri.Query).Get(0) et il extraira le premier paramètre. `

0 votes

Existe-t-il un outil .NET pour construire une url de requête paramétrée ?

54voto

Sergej Andrejev Points 4052

C'est probablement ce que vous voulez

var uri = new Uri("http://domain.test/Default.aspx?var1=true&var2=test&var3=3");
var query = HttpUtility.ParseQueryString(uri.Query);

var var2 = query.Get("var2");

41voto

alsed42 Points 600

Voici une autre alternative si, pour une raison quelconque, vous ne pouvez ou ne voulez pas utiliser HttpUtility.ParseQueryString() .

Ce système est conçu pour être quelque peu tolérant vis-à-vis des chaînes de requête "malformées", c'est-à-dire qu'il n'est pas nécessaire d'avoir recours à un système d'alerte. http://test/test.html?empty= devient un paramètre avec une valeur vide. L'appelant peut vérifier les paramètres si nécessaire.

public static class UriHelper
{
    public static Dictionary<string, string> DecodeQueryParameters(this Uri uri)
    {
        if (uri == null)
            throw new ArgumentNullException("uri");

        if (uri.Query.Length == 0)
            return new Dictionary<string, string>();

        return uri.Query.TrimStart('?')
                        .Split(new[] { '&', ';' }, StringSplitOptions.RemoveEmptyEntries)
                        .Select(parameter => parameter.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries))
                        .GroupBy(parts => parts[0],
                                 parts => parts.Length > 2 ? string.Join("=", parts, 1, parts.Length - 1) : (parts.Length > 1 ? parts[1] : ""))
                        .ToDictionary(grouping => grouping.Key,
                                      grouping => string.Join(",", grouping));
    }
}

Test

[TestClass]
public class UriHelperTest
{
    [TestMethod]
    public void DecodeQueryParameters()
    {
        DecodeQueryParametersTest("http://test/test.html", new Dictionary<string, string>());
        DecodeQueryParametersTest("http://test/test.html?", new Dictionary<string, string>());
        DecodeQueryParametersTest("http://test/test.html?key=bla/blub.xml", new Dictionary<string, string> { { "key", "bla/blub.xml" } });
        DecodeQueryParametersTest("http://test/test.html?eins=1&zwei=2", new Dictionary<string, string> { { "eins", "1" }, { "zwei", "2" } });
        DecodeQueryParametersTest("http://test/test.html?empty", new Dictionary<string, string> { { "empty", "" } });
        DecodeQueryParametersTest("http://test/test.html?empty=", new Dictionary<string, string> { { "empty", "" } });
        DecodeQueryParametersTest("http://test/test.html?key=1&", new Dictionary<string, string> { { "key", "1" } });
        DecodeQueryParametersTest("http://test/test.html?key=value?&b=c", new Dictionary<string, string> { { "key", "value?" }, { "b", "c" } });
        DecodeQueryParametersTest("http://test/test.html?key=value=what", new Dictionary<string, string> { { "key", "value=what" } });
        DecodeQueryParametersTest("http://www.google.com/search?q=energy+edge&rls=com.microsoft:en-au&ie=UTF-8&oe=UTF-8&startIndex=&startPage=1%22",
            new Dictionary<string, string>
            {
                { "q", "energy+edge" },
                { "rls", "com.microsoft:en-au" },
                { "ie", "UTF-8" },
                { "oe", "UTF-8" },
                { "startIndex", "" },
                { "startPage", "1%22" },
            });
        DecodeQueryParametersTest("http://test/test.html?key=value;key=anotherValue", new Dictionary<string, string> { { "key", "value,anotherValue" } });
    }

    private static void DecodeQueryParametersTest(string uri, Dictionary<string, string> expected)
    {
        Dictionary<string, string> parameters = new Uri(uri).DecodeQueryParameters();
        Assert.AreEqual(expected.Count, parameters.Count, "Wrong parameter count. Uri: {0}", uri);
        foreach (var key in expected.Keys)
        {
            Assert.IsTrue(parameters.ContainsKey(key), "Missing parameter key {0}. Uri: {1}", key, uri);
            Assert.AreEqual(expected[key], parameters[key], "Wrong parameter value for {0}. Uri: {1}", parameters[key], uri);
        }
    }
}

0 votes

Utile pour les projets Xamarin, où HttpUtility n'est pas disponible

0 votes

Il s'agit d'une extension très utile qui peut également être adaptée aux URI partiels. Je suggère d'ajouter un Uri.UnescapeDataString() aux valeurs des paramètres ou de renommer la méthode en quelque chose d'autre que "decode" s'ils ne sont pas réellement décodés. ?empty= n'est pas une chaîne de requête malformée. Il y a juste un paramètre avec une chaîne vide comme valeur. C'est tout à fait normal, donc merci d'en tenir compte.

0 votes

Cela ne correspond pas au comportement de HttpUtility.ParseQueryString() car il n'effectue pas un décodage correct des valeurs. Comme indiqué dans les cas de test des résultats attendus { "startPage", "1%22" } la valeur est toujours codée en pourcentage mais serait 1" s'il a été analysé par la classe HttpUtility.

16voto

Tom Ritter Points 44352

On dirait que vous devez boucler sur les valeurs de myUri.Query et l'analyser à partir de là.

 string desiredValue;
 foreach(string item in myUri.Query.Split('&'))
 {
     string[] parts = item.Replace("?", "").Split('=');
     if(parts[0] == "desiredKey")
     {
         desiredValue = parts[1];
         break;
     }
 }

Cependant, je n'utiliserais pas ce code sans le tester sur un certain nombre d'URL malformées. Il pourrait être cassé sur certaines/toutes ces URL :

  • hello.html?
  • hello.html?valuelesskey
  • hello.html?key=value=hi
  • hello.html?hi=value?&b=c
  • etc.

15voto

Mo Gauvin Points 91

@Andrew et @CZFox

J'ai eu le même bug et j'ai trouvé que la cause était que le paramètre 1 est en fait : http://www.example.com?param1 et non param1 ce qui est ce que l'on attendrait.

La suppression de tous les caractères avant et après le point d'interrogation résout ce problème. Donc, en substance, le HttpUtility.ParseQueryString ne nécessite qu'un paramètre de chaîne de requête valide ne contenant que des caractères après le point d'interrogation comme dans :

HttpUtility.ParseQueryString ( "param1=good&param2=bad" )

Ma solution de rechange :

string RawUrl = "http://www.example.com?param1=good&param2=bad";
int index = RawUrl.IndexOf ( "?" );
if ( index > 0 )
    RawUrl = RawUrl.Substring ( index ).Remove ( 0, 1 );

Uri myUri = new Uri( RawUrl, UriKind.RelativeOrAbsolute);
string param1 = HttpUtility.ParseQueryString( myUri.Query ).Get( "param1" );`

0 votes

Lorsque l'URI est instancié, je reçois l'erreur "Invalid URI : Le format de l'URI n'a pas pu être déterminé". Je ne pense pas que cette solution fonctionne comme prévu.

0 votes

@PaulMatthews, vous avez raison. À l'époque de cette solution, j'utilisais l'ancien .net framework 2.0. Pour confirmer votre affirmation, j'ai copié et collé cette solution dans LINQPad v2 de Joseph Albahara et j'ai reçu la même erreur que vous avez mentionnée.

0 votes

@PaulMatthews, Pour corriger, supprimez la ligne qui dit Uri myUri = new Uri( RawUrl ) ; et passez simplement RawUrl à la dernière déclaration comme dans : string param1 = HttpUtility.ParseQueryString( RawUrl ).Get( "param2" ) ;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X