2010-07-30 5 views
1

Je construis une URL lors de l'exécution. Jusqu'ici j'ai fait commeQuelle est la meilleure façon d'effectuer une concaténation de chaîne pour créer une URL dynamique?

public string BuildURLAndNavigate(CodeType codeType) 
{  
    string vURL = string.Empty; 

    string mstrNavServer = "http://some.com/nav"; 
    vURL = ConcatenateString(mstrNavServer , "/somepage.asp?app=myapp"); 

    //Build Code Type 
    switch (codeType) 
    { 
    case CodeType.Series: 
     vURL = ConcatenateString(vURL , "&tools=ser"); 
     break; 
    case CodeType.DataType: 
     vURL = ConcatenateString(vURL , "&tools=dt"); 
     break; 
    } 

    //build version 
    string VER_NUM = "5.0"; 
    vURL = ConcatenateString(vURL , ConcatenateString("&vsn=" , VER_NUM));   
    return vURL; 
    } 

    private string ConcatenateString(string expression1, string expression2) 
    { 
     return string.Concat(expression1 + expression2); 
    } 

Mais je ne suis pas heureux avec celui que je fais. Je suis sûr qu'il y a certainement une meilleure pratique/meilleure approche que celle-ci.

Veuillez m'aider à guider pour la même chose.

Merci

+1

Qu'est-ce qui vous satisfait pas? Que pensez-vous les lacunes sont? – Oded

Répondre

7

Jamais créer des URL à l'aide d'une chaîne s, constructeurs de chaînes, concaténations de chaînes.

Vous pouvez commencer par définir une collection personnalisée qui prendra en charge le codage URL correctement une valeur ajoutée à elle:

public class HttpNameValueCollection : NameValueCollection 
{ 
    public override void Add(string name, string value) 
    { 
     base.Add(name, HttpUtility.UrlEncode(value)); 
    } 

    public override string ToString() 
    { 
     return string.Join("&", Keys.Cast<string>().Select(
      key => string.Format("{0}={1}", key, this[key]))); 
    } 
} 

Et puis simplement:

public string BuildURLAndNavigate() 
{ 
    var uriBuilder = new UriBuilder("http://some.com/nav/somepage.asp"); 
    var values = new HttpNameValueCollection(); 
    values.Add("app", "myapp"); 

    switch (codeType) 
    { 
     case CodeType.Series: 
      values.Add("tools", "ser"); 
      break; 
     case CodeType.DataType: 
      values.Add("tools", "dt"); 
      break; 
    } 

    // You could even do things like this without breaking your urls 
    values.Add("p", "http://www.example.com?p1=v1&p2=v2"); 


    string VER_NUM = "5.0"; 
    values.Add("vsn", VER_NUM); 
    uriBuilder.Query = values.ToString(); 
    return uriBuilder.ToString(); 
} 
+0

Pourquoi ne jamais utiliser la concaténation? Il ne concatène pas les valeurs entrées par l'utilisateur dans son URL. Il ne fait que concaténer des valeurs constantes. Il n'y a donc aucune chance d'une attaque par injection. Bien que j'aime vraiment cet exemple de code et que je puisse voir son utilité dans de nombreux cas (et j'ai l'intention de le voler pour mon usage personnel :) dans ce cas, j'ai vraiment envie de pousser une punaise avec un marteau. – Zippit

+1

Je fais toujours la promotion des meilleures pratiques. Oui, dans ce cas, il ne peut pas y avoir d'injection, mais c'est peut-être une version simplifiée du vrai code. Peut-être que demain, il y aura un autre développeur qui viendra au projet et ajoutera une valeur de paramètre dynamique. –

+1

StackOverflow est également un site bien référencé. Il y a des centaines de développeurs qui copient et collent constamment des extraits de code de la réponse acceptée sans vraiment comprendre ce qu'ils font (car ils pensent que si ça marche dans son cas ça marchera dans le mien aussi) et ils sont surpris quand ils reçoivent des appels nocturnes les clients qui ne comprennent pas pourquoi l'application tronque les valeurs qu'ils saisissent dans la zone de texte :-) –

8

Vous pouvez utiliser un StringBuilder:

public string BuildURLAndNavigate(CodeType codeType) 
{ 
    StringBuilder vURL = new StringBuilder(); 

    vURL.Append("http://some.com/nav"); 
    vURL.Append("/somepage.asp?app=myapp"); 

    //Build Code Type 
    switch (codeType) 
    { 
     case CodeType.Series: 
      vURL.Append("&tools=ser"); 
      break; 
     case CodeType.DataType: 
      vURL.Append("&tools=dt"); 
      break; 
    } 

    //build version 
    string VER_NUM = "5.0"; 
    vURL.AppendFormat("&vsn={0}", VER_NUM);   

    return vURL.ToString(); 
} 
+0

Le générateur de chaînes est trop puissant ici. Pour la quantité de concaténation qui se passe ici, vous allez probablement voir plus d'un coup de perf, puis un coup de pouce. – Zippit

+0

Pas nécessairement. (Gardez un constructeur de cordes autour). Il permet également une API plus flexible avec AppendFormat inclus;) – TomTom

0

Oui, StringBuilder est la meilleure solution ici. Vous pouvez trouver plus d'informations sur la page MSDN: http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx

StringBuilder contient des méthodes très utiles:

StringBuilder.Append
information à la Ajoute fin de la StringBuilder actuelle.

StringBuilder.AppendFormat
Remplace un spécificateur de format transmis dans une chaîne avec du texte formaté.

StringBuilder.Insert
Insère une chaîne ou un objet dans l'index spécifié du StringBuilder actuel. StringBuilder.Remove
Supprime un nombre spécifié de caractères du StringBuilder actuel.

StringBuilder.Replace
Remplace un caractère spécifié à un index spécifié.

+0

Les URL ne doivent pas être traitées comme des chaînes simples je suppose ... ... la classe Uri est faite pour gérer les références relatives ... – santa

2

Ce que vous faites est bien - c'est simple et compréhensible. Toute personne qui lit le code peut comprendre ce que vous faites. En termes de performances, vous ne faites pas beaucoup de manipulation de chaînes, donc à moins de construire des chaînes énormes ou de faire cette opération des milliers de fois par minute, vous n'utiliserez pas beaucoup StringBuilder. Avant d'optimiser ce code, testez ses performances. Vous trouverez probablement qu'il y a d'autres goulets d'étranglement plus importants sur lesquels travailler en premier.

Le seul vrai commentaire que j'ai est que votre fonction ConcatenateString semble superflue. Il n'ajoute vraiment rien au code et tout l'appel à cela peut simplement être remplacé par string.Concat. Comme mentionné dans la réponse de @abatishchev, vous devriez utiliser (str1, str2) et non (str1 + str2), car cela détruit la raison de l'appel.

2

Comme Saxon Druce dit: Vous pouvez utiliser un StringBuilder, mais, selon les valeurs codeType, vous pouvez éliminer l'interrupteur trop:

public string BuildURLAndNavigate(CodeType codeType) 
{ 
    StringBuilder vURL = new StringBuilder(); 

    vURL.Append("http://some.com/nav"); 
    vURL.Append("/somepage.asp?app=myapp"); 

    //Build Code Type 
    vURL.Append(codeType == CodeType.Series ? "&tools=ser" : "&tools=dt"); 

    //build version 
    string VER_NUM = "5.0"; 
    vURL.AppendFormat("&vsn={0}", VER_NUM);   

    return vURL.ToString(); 
} 
+0

Cela peut ne pas être la même chose comme éliminant swicth selon s'il y a plus de deux valeurs pour l'énumération. Il se peut que certaines valeurs n'aient pas besoin d'ajouter quoi que ce soit à l'URL. Vous avez probablement raison mais pensé qu'il valait la peine de mentionner explicitement. – Chris

+0

Oui, j'ai essayé de faire allusion à ce cas dans l'expression "en fonction des valeurs CodeType", mais cela mérite vraiment d'être plus explicite, Chris. Merci! –

2

Do

return string.Concat(expression1, expression2); 

pas

return string.Concat(expression1 + expression2); 
+0

Haha, bon endroit :) – cjk

2

ne serait pas le droit moyen de faire cela soit d'utiliser la classe Uri ou la classe UriBuilder?

par exemple Uri Uri cteur surchargez (Uri, string):

public Uri(
    Uri baseUri, 
    string relativeUri 
); 


Uri baseUri = new Uri("http://www.contoso.com"); 
Uri myUri = new Uri(baseUri, "catalog/shownew.htm"); 
Console.WriteLine(myUri.ToString()); 

http://msdn.microsoft.com/en-us/library/aa332624(v=VS.71).aspx

0

personnellement je serais enclin à juste string.format quelque chose comme ça:

public string BuildURLAndNavigate(CodeType codeType) 
{  
    string vURL = "http://some.com/nav/somepage.asp?app=myapp&tools={0}&vsn={1}"; 
    string codevalue = ""; 
    //Build Code Type 
    switch (codeType) 
    { 
    case CodeType.Series: 
     codevalue = "ser"; 
     break; 
    case CodeType.DataType: 
     codevalue = "dt"; 
     break; 
    } 

    //build version 
    string version = "5.0"; 
    return string.Format(vURL, codevalue, version); 
    } 
} 

Excuses s'il y a des erreurs dans cela, je n'étais pas dans VS en l'écrivant ainsi il pourrait y avoir quelques fautes de frappe que je n'ai pas remarquées - vous devriez avoir l'idée pourtant.

La raison pour laquelle j'aime cette méthode, c'est parce que vous pouvez voir immédiatement quelle est la forme globale de votre URL, ce qui peut vous aider à comprendre à peu près l'URL retournée.

0

Afin de conserver toutes les variables à un seul endroit, pourrait-on utiliser la solution suivante

public string BuildURLAndNavigate(CodeType codeType) 
    { 
     //code here - switch statement to calculate the codeValue 

     //Anonymous type - To keep all variables at one place  
     var urlComponents = new { 
           server = "http://some.com/nav", 
           pageName="/somepage.asp?app=myapp", 
           codevalue = "", //Replace with the actual value calculated in switch statement 
           versionPart="&vsn=", 
           version = "5.0" 
           }; 


     StringBuilder vURL = new StringBuilder(); 
     vURL.Append(urlComponents.server); 
     vURL.Append(urlComponents.pageName); 
     vURL.Append(urlComponents.codevalue); 
     vURL.Append(urlComponents.versionPart); 
     vURL.Append(urlComponents.version); 
     return vURL.ToString(); 

    } 
Questions connexes