2009-05-11 18 views
25

Die Uri-Klasse standardmäßig RFC 2396. Für OpenID und OAuth zu erfüllen, muss ich Uri mit RFC konsequente Flucht 3986.Wie kommt man Uri.EscapeDataString mit RFC 3986

Vom System.Uri class documentation:

Standardmäßig sind alle reservierten Zeichen im URI gemäß RFC 2396 maskiert. Dieses Verhalten ändert sich, wenn die Analyse von internationalen Ressourcen-IDs oder internationalen Domänennamen aktiviert ist. In diesem Fall werden reservierte Zeichen im URI gemäß RFC 3986 und RFC 3987 gemerkt.

In der Dokumentation wird auch, dass diese IRI-Modus zu aktivieren und somit bedeutet die RFC 3986 Verhalten ein uri Abschnitt Element hinzugefügt wird machine.config und diese zu Ihrem app/web.config-Datei:

<configuration> 
    <uri> 
    <idn enabled="All" /> 
    <iriParsing enabled="true" /> 
    </uri> 
</configuration> 

Aber ob diese vorhanden ist, In der .config-Datei oder nicht, erhalte ich das gleiche (nicht-3986) Escaping-Verhalten für eine .NET 3.5 SP1-Anwendung. Was muss ich noch tun, um Uri.EscapeDataString zur Verwendung der RFC 3986-Regeln zu erhalten? (speziell, um die reservierten Zeichen zu umgehen, wie in diesem RFC definiert)

+0

Ich habe einige Community-Inhalt für den Tippfehler in der Syntax Beispiel hinzugefügt. –

+0

Ich habe dies intern als Bug mit dem .NET Framework abgelegt (ich arbeite für MSFT). Sie erkennen dies als einen Dokumentationsfehler an, da diese Konfigurationseinstellung die Uri-Klasse * nicht * dazu bringt, sich wie RFC 3986 in Bezug auf das Entkommen zu verhalten. –

Antwort

31

Nachdem Uri.EscapeDataString das Verhalten von RFC 3986 nicht übernehmen konnte, schrieb ich meine eigene RFC 3986-kompatible Escaping-Methode. Es nutzt Uri.EscapeDataString und "aktualisiert" dann die Einhaltung der RFC 3986-Konformität.

/// <summary> 
/// The set of characters that are unreserved in RFC 2396 but are NOT unreserved in RFC 3986. 
/// </summary> 
private static readonly string[] UriRfc3986CharsToEscape = new[] { "!", "*", "'", "(", ")" }; 

/// <summary> 
/// Escapes a string according to the URI data string rules given in RFC 3986. 
/// </summary> 
/// <param name="value">The value to escape.</param> 
/// <returns>The escaped value.</returns> 
/// <remarks> 
/// The <see cref="Uri.EscapeDataString"/> method is <i>supposed</i> to take on 
/// RFC 3986 behavior if certain elements are present in a .config file. Even if this 
/// actually worked (which in my experiments it <i>doesn't</i>), we can't rely on every 
/// host actually having this configuration element present. 
/// </remarks> 
internal static string EscapeUriDataStringRfc3986(string value) { 
    // Start with RFC 2396 escaping by calling the .NET method to do the work. 
    // This MAY sometimes exhibit RFC 3986 behavior (according to the documentation). 
    // If it does, the escaping we do that follows it will be a no-op since the 
    // characters we search for to replace can't possibly exist in the string. 
    StringBuilder escaped = new StringBuilder(Uri.EscapeDataString(value)); 

    // Upgrade the escaping to RFC 3986, if necessary. 
    for (int i = 0; i < UriRfc3986CharsToEscape.Length; i++) { 
     escaped.Replace(UriRfc3986CharsToEscape[i], Uri.HexEscape(UriRfc3986CharsToEscape[i][0])); 
    } 

    // Return the fully-RFC3986-escaped string. 
    return escaped.ToString(); 
} 
+2

Wissen Sie, ob .net 4.5 tatsächlich das endlich behebt? http://msdn.microsoft.com/en-us/library/hh367887(v=VS.110).aspx –

+1

Ich glaube nicht. –

+2

.NET 4.5 hat das behoben. –

0

Welche Version des Frameworks verwenden Sie? Es sieht so aus, als ob viele dieser Änderungen im Zeitrahmen ".NET Framework 3.5. 3.0 SP1 und 2.0 SP1" (from MSDN) vorgenommen wurden.

+1

Ich habe hinzugefügt, dass ich .NET 3.5 SP1 zu meiner Frage verwende. Ich bemerke mit einiger Belustigung, dass der MSDN-Artikel, den Sie verlinken, grob mit sich selbst inkonsistent ist, ungültiges XML, Uri und Uri austauschbar verwendet wird, wenn Groß- und Kleinschreibung wichtig ist, und , wenn der Wert stattdessen "all" sein soll von "wahr", wie der Doc selbst später zeigt. :) –

-1

Ich hätte keine bessere Antwort (entweder 100% oder 100% Rahmen Neuimplementierung) finden, so habe ich diese Gräuel erstellt. Scheint mit OAuth zu arbeiten.

class al_RFC3986 
{ 
    public static string Encode(string s) 
    { 
     StringBuilder sb = new StringBuilder(s.Length*2);//VERY rough estimate 
     byte[] arr = Encoding.UTF8.GetBytes(s); 

     for (int i = 0; i < arr.Length; i++) 
     { 
      byte c = arr[i]; 

      if(c >= 0x41 && c <=0x5A)//alpha 
       sb.Append((char)c); 
      else if(c >= 0x61 && c <=0x7A)//ALPHA 
       sb.Append((char)c); 
      else if(c >= 0x30 && c <=0x39)//123456789 
       sb.Append((char)c); 
      else if (c == '-' || c == '.' || c == '_' || c == '~') 
       sb.Append((char)c); 
      else 
      { 
       sb.Append('%'); 
       sb.Append(Convert.ToString(c, 16).ToUpper()); 
      } 
     } 
     return sb.ToString(); 
    } 
} 
+0

Grund für downvotes? –

+0

Weil die Antwort ist schlecht Geschmack imo. – Anders

3

Dies wurde durch Standard .NET 4.5 zu arbeiten, sehen here in tatsächlich fixiert.

Ich habe gerade eine neue Bibliothek PUrify genannt (nach dem in dieser Ausgabe läuft), die damit umgehen wird immer für .NET Pre 4.5 (funktioniert für 3.5) und Mono durch eine Variation des Ansatzes in dieser Arbeit post. PUrify ändert EscapeDataString nicht, aber Sie können Uris mit reservierten Zeichen verwenden, die nicht maskiert werden.

0

Ich weiß, dass diese Frage und die Antworten ein paar Jahre alt sind, aber ich dachte, ich würde meine Entdeckung teilen, wenn ich Schwierigkeiten hatte, compliance under .Net 4.5 zu bekommen.

Wenn Ihr Code unter asp.net ausgeführt wird und Sie das Projekt nur auf 4.5 festlegen und auf einem Computer mit 4.5 oder höher ausführen, erhalten Sie möglicherweise weiterhin 4.0-Verhalten. Sie müssen sicherstellen, dass <httpRuntime targetFramework="4.5" /> in der Datei web.config festgelegt ist.

Von this blog article on msdn,

Wenn kein <httpRuntime targetFramework> vorhanden ist Attribut in Web.config, gehen wir davon aus, dass die Anwendung 4.0 Macken Verhalten wollte.