2010-02-23 7 views
12

muszę zwrócić następujący adres URL w mojej aplikacji:System.Net.Uri z postaciami urlencoded

http://feedbooks.com/type/Crime%2FMystery/books/top 

Kiedy uruchomić następujący kod:

Uri myUri = new Uri("http://feedbooks.com/type/Crime%2FMystery/books/top"); 

Konstruktor Uri dekoduje %2F do literalny /, a otrzymuję błąd 404, ponieważ zmienił on adres URL na:

http://feedbooks.com/type/Crime/Mystery/books/top 

Klasa Uri ma konstruktor, który przyjmuje parametr dontEscape, ale ten konstruktor jest przestarzały i ustawienie go na true nie daje żadnego efektu.

Moją pierwszą myślą było zrobić coś takiego:

Uri myUri = new Uri("http://feedbooks.com/type/Crime%252FMystery/books/top"); 

z nadzieją, że będzie konwertować %25 w dosłownym %, ale to nie działało.

Wszelkich pomysłów, jak utworzyć poprawny obiekt Uri dla tego konkretnego adresu URL w .NET?

+0

um ... Próbowałeś \% (lub \\%) ... :( – apandit

+0

Kocham pytanie. Otóż, proszę dać odpowiedź Java dla java.io.URI, który ma taką samą obchodzi problem, ale bez flag (w pobliżu, jak mogę powiedzieć)! – davidbak

Odpowiedz

5

wpadłem na ten sam problem przy użyciu 2,0 ...

odkryłem obejście zamieszczonych na this blog:

// System.UriSyntaxFlags is internal, so let's duplicate the flag privately 
private const int UnEscapeDotsAndSlashes = 0x2000000; 

public static void LeaveDotsAndSlashesEscaped(Uri uri) 
{ 
    if (uri == null) 
    { 
     throw new ArgumentNullException("uri"); 
    } 

    FieldInfo fieldInfo = uri.GetType().GetField("m_Syntax", BindingFlags.Instance | BindingFlags.NonPublic); 
    if (fieldInfo == null) 
    { 
     throw new MissingFieldException("'m_Syntax' field not found"); 
    } 
    object uriParser = fieldInfo.GetValue(uri); 

    fieldInfo = typeof(UriParser).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic); 
    if (fieldInfo == null) 
    { 
     throw new MissingFieldException("'m_Flags' field not found"); 
    } 
    object uriSyntaxFlags = fieldInfo.GetValue(uriParser); 

    // Clear the flag that we don't want 
    uriSyntaxFlags = (int)uriSyntaxFlags & ~UnEscapeDotsAndSlashes; 

    fieldInfo.SetValue(uriParser, uriSyntaxFlags); 
} 

działa idealnie.

Nadzieja to pomaga (lepiej późno niż wcale!)

+0

Niesamowite! Stackoverflow nigdy nie przestaje mnie zadziwiać –

+0

Cieszę się, że mogłem pomóc ... –

2

To jest bug Po pewnym czasie wróciłem. Powinien zostać naprawiony w wersji 4.0, ale nie wstrzymuję oddechu. Wygląda na to, że nadal jest problemem w RC.

+0

Ah. Czy znasz jakieś obejście dla wdrożenia 3.5? –

+0

Niestety, ale nie znalazłem żadnego obejścia dla tego jeszcze.Jest to zły. to –

7

To trochę łatwiejsze w .NET 4.0. W pliku konfiguracyjnym można ustawić następujące ustawienia:

<uri> 
<schemeSettings> 
    <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" /> 
</schemeSettings> 
</uri> 

Działa tylko w przypadku schematów "http" i "https".

Albo tutaj jest nowa wersja metody LeaveDotsAndSlashesEscaped. To nie wymaga szczególnej instancji Uri, wystarczy zadzwonić, kiedy aplikacja uruchamia się:

private void LeaveDotsAndSlashesEscaped() 
{ 
    var getSyntaxMethod = 
     typeof (UriParser).GetMethod("GetSyntax", BindingFlags.Static | BindingFlags.NonPublic); 
    if (getSyntaxMethod == null) 
    { 
     throw new MissingMethodException("UriParser", "GetSyntax"); 
    } 

    var uriParser = getSyntaxMethod.Invoke(null, new object[] { "http" }); 

    var setUpdatableFlagsMethod = 
     uriParser.GetType().GetMethod("SetUpdatableFlags", BindingFlags.Instance | BindingFlags.NonPublic); 
    if (setUpdatableFlagsMethod == null) 
    { 
     throw new MissingMethodException("UriParser", "SetUpdatableFlags"); 
    } 

    setUpdatableFlagsMethod.Invoke(uriParser, new object[] {0}); 
} 
1

Łącząc 2 wcześniejsze odpowiedzi można mieć metodę, wystarczy zadzwonić raz w procesie, który działa zarówno na. net 4 i .net 3.5.

// System.UriSyntaxFlags is internal, so let's duplicate the flag privately 
private const int UnEscapeDotsAndSlashes = 0x2000000; 

private void LeaveDotsAndSlashesEscaped() 
{ 
    var getSyntaxMethod = 
     typeof (UriParser).GetMethod("GetSyntax", BindingFlags.Static | BindingFlags.NonPublic); 
    if (getSyntaxMethod == null) 
    { 
     throw new MissingMethodException("UriParser", "GetSyntax"); 
    } 

    var uriParser = getSyntaxMethod.Invoke(null, new object[] { "http" }); 

    FieldInfo flagsFieldInfo = typeof(UriParser).GetField("m_Flags", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.Instance); 

    if (flagsFieldInfo == null) 
    { 
     throw new MissingFieldException("UriParser", "m_Flags"); 
    } 
    int flags = (int) flagsFieldInfo.GetValue(uriParser); 
    // unset UnEscapeDotsAndSlashes flag and leave the others untouched 
    flags = flags & ~UnEscapeDotsAndSlashes; 
    flagsFieldInfo.SetValue(uriParser, flags); 

} 
Powiązane problemy