2010-02-23 8 views
12

que necesito para solicitar la siguiente URL dentro de mi solicitud:System.Net.Uri con caracteres urlencoded

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

Cuando ejecuto el siguiente código:

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

El constructor Uri decodifica la %2F en un literal /, y me aparece un error 404 porque ha cambiado la URL a:

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

La clase Uri tiene un constructor que toma un parámetro dontEscape, pero ese constructor está en desuso y establecerlo en true no tiene ningún efecto.

Mi primera idea fue hacer algo como:

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

Con la esperanza de que se convertiría en un literal %25%, pero eso tampoco funcionó.

¿Alguna idea de cómo crear un objeto correcto Uri para esta URL en particular en .NET?

+0

um ... ¿Usted intentó \% (o \\%) ... :( – apandit

+0

Me encanta la pregunta. Ahora, por favor, dar una respuesta Java para java.io.URI que tiene la misma maldita problema, pero sin los indicadores (cerca de lo que puedo decir)! – davidbak

Respuesta

5

me encontré con el mismo problema utilizando 2,0 ...

he descubierto una solución publicado en 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); 
} 

funciona perfectamente.

Esperanza esto ayuda (mejor tarde que nunca!)

+0

¡Impresionante! Stackoverflow nunca deja de sorprenderme. –

+0

Me alegro de poder ayudar ... –

2

Esto es un bug que archivé hace un tiempo. Se supone que está arreglado en 4.0, pero no estoy conteniendo la respiración. Aparentemente sigue siendo un problema en el RC.

+0

Ah. ¿Conoces alguna solución para una implementación 3.5? –

+0

Lo sentimos, pero no he encontrado ninguna solución para esto todavía. Es una mala. Ir a votar it. –

7

Es un poco más fácil en .NET 4.0. Puede poner una configuración en su archivo de configuración de esta manera:

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

Solo funciona para los esquemas 'http' y 'https'.

O aquí hay una nueva versión del método LeaveDotsAndSlashesEscaped. No necesita una instancia de Uri en particular, simplemente llamarlo cuando se inicia la aplicación:

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

Al combinar las 2 respuestas anteriores puede tener un método sólo tiene que llamar una vez por proceso que funciona tanto en. net 4 y .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); 

} 
Cuestiones relacionadas