Clase System.Uri
En este artículo se proporcionan comentarios adicionales a la documentación de referencia de esta API.
Un URI es una representación compacta de un recurso disponible para la aplicación en la intranet o En Internet. La Uri clase define las propiedades y los métodos para controlar los URI, incluido el análisis, la comparación y la combinación. Las Uri propiedades de clase son de solo lectura; para crear un objeto modificable, use la UriBuilder clase .
Los URI relativos (por ejemplo, "/new/index.htm") deben expandirse con respecto a un URI base para que sean absolutos. El MakeRelativeUri método se proporciona para convertir los URI absolutos en URI relativos cuando sea necesario.
Los Uri constructores no escapan a las cadenas de URI si la cadena es un URI bien formado, incluido un identificador de esquema.
Las Uri propiedades devuelven una representación de datos canónica en codificación con escape, con todos los caracteres con valores Unicode mayores que 127 reemplazados por sus equivalentes hexadecimales. Para colocar el URI en forma canónica, el Uri constructor realiza los pasos siguientes:
Convierte el esquema URI en minúsculas.
Convierte el nombre de host en minúsculas.
Si el nombre de host es una dirección IPv6, se usa la dirección IPv6 canónica. ScopeId y otros datos IPv6 opcionales se quitan.
Quita los números de puerto predeterminados y vacíos.
Convierte rutas de acceso implícitas de archivo sin el esquema de file:// (por ejemplo, "C:\my\file") en rutas de acceso de archivo explícitas con el esquema file://.
Los caracteres de escape (también conocidos como octetos codificados por porcentaje) que no tienen un propósito reservado se descodifican (también conocidos como sin escape). Estos caracteres no servidos incluyen mayúsculas y minúsculas (%41-%5A y %61-%7A), dígitos decimales (%30-%39), guion (%2D), punto (%2E), subrayado (%5F) y tilde (%7E).
Canónicamente la ruta de acceso de los URI jerárquicos mediante la compactación de secuencias como /./, /.. /, y // (si la secuencia es de escape o no). Tenga en cuenta que hay algunos esquemas para los que estas secuencias no están compactadas.
En el caso de los URI jerárquicos, si el host no finaliza con una barra diagonal (/), se agrega una.
De forma predeterminada, los caracteres reservados del URI se escapen de acuerdo con RFC 2396. Este comportamiento cambia si los identificadores de recursos internacionales o el análisis de nombres de dominio internacional están habilitados en cuyo caso los caracteres reservados en el URI se escapan de acuerdo con RFC 3986 y RFC 3987.
Como parte de la canónica en el constructor para algunos esquemas, los segmentos de puntos y los segmentos vacíos (, /../
y //
) se compactan (/./
es decir, se quitan). Los esquemas para los que Uri compacta segmentos incluyen http, https, tcp, net.pipe y net.tcp. Para algunos otros esquemas, estas secuencias no se compactan. En el siguiente fragmento de código se muestra cómo se ve la compactación en la práctica. Las secuencias de escape están sin escape, si es necesario, y luego se compactan.
var uri = new Uri("http://myUrl/../.."); // http scheme, unescaped
OR
var uri = new Uri("http://myUrl/%2E%2E/%2E%2E"); // http scheme, escaped
OR
var uri = new Uri("ftp://myUrl/../.."); // ftp scheme, unescaped
OR
var uri = new Uri("ftp://myUrl/%2E%2E/%2E%2E"); // ftp scheme, escaped
Console.WriteLine($"AbsoluteUri: {uri.AbsoluteUri}");
Console.WriteLine($"PathAndQuery: {uri.PathAndQuery}");
Cuando se ejecuta este código, devuelve una salida similar al texto siguiente.
AbsoluteUri: http://myurl/
PathAndQuery: /
Puede transformar el contenido de la Uri clase de una referencia de URI codificada con escape a una referencia de URI legible mediante el ToString método . Tenga en cuenta que es posible que algunos caracteres reservados todavía se escapen en la salida del ToString método . Esto es para admitir la reconstrucción inequívoca de un URI a partir del valor devuelto por ToString.
Algunos URI incluyen un identificador de fragmento o una consulta o ambas. Un identificador de fragmento es cualquier texto que siga un signo de número (#), no incluido el signo de número; el texto del fragmento se almacena en la Fragment propiedad . La información de consulta es cualquier texto que siga un signo de interrogación (?) en el URI; el texto de la consulta se almacena en la Query propiedad .
Nota:
La clase URI admite el uso de direcciones IP en la notación cuádruple para el protocolo IPv4 y el protocolo hexadecimal de dos puntos para el protocolo IPv6. No olvide incluir la dirección IPv6 entre corchetes, como en http://[::1].
Compatibilidad con identificadores de recursos internacionales
Las direcciones web normalmente se expresan mediante identificadores uniformes de recursos que constan de un conjunto muy restringido de caracteres:
- Letras ASCII mayúsculas y minúsculas del alfabeto inglés.
- Dígitos del 0 al 9.
- Un número reducido de otros símbolos ASCII.
Las especificaciones de los URI se documentan en RFC 2396, RFC 2732, RFC 3986 y RFC 3987 publicados por internet Engineering Task Force (IETF).
Los identificadores que facilitan la necesidad de identificar recursos que usan idiomas distintos del inglés y permiten caracteres no ASCII (caracteres en el juego de caracteres Unicode/ISO 10646) se conocen como identificadores de recursos internacionales (IRIs). Las especificaciones de los IRI están documentadas en RFC 3987, publicado por el IETF. El uso de IRI permite que una dirección URL contenga caracteres Unicode.
En .NET Framework 4.5 y versiones posteriores, IRI siempre está habilitado y no se puede cambiar con una opción de configuración. Puede establecer una opción de configuración en machine.config o en el archivo app.config para especificar si desea analizar el nombre de dominio internacionalizado (IDN) aplicado al nombre de dominio. Por ejemplo:
<configuration>
<uri>
<idn enabled="All" />
</uri>
</configuration>
Al habilitar IDN, se convierten todas las etiquetas Unicode de un nombre de dominio en sus equivalentes de Punycode. Los nombres de Punycode solo contienen caracteres ASCII y siempre empiezan con el prefijo xn--. De este modo, se admiten los servidores DNS existentes en Internet, ya que la mayoría de los servidores DNS solo admite caracteres ASCII (vea RFC 3940).
La habilitación de IDN afecta al valor de la Uri.DnsSafeHost propiedad . La habilitación de IDN también puede cambiar el comportamiento de los Equalsmétodos , OriginalString, GetComponentsy IsWellFormedOriginalString .
Hay tres valores posibles para IDN en función de los servidores DNS que se usan:
idn enabled = All
Este valor convierte cualquier nombre de dominio Unicode a su equivalente Punycode (nombres IDN).
idn enabled = AllExceptIntranet
Este valor convertirá todos los nombres de dominio Unicode que no están en la intranet local para que se utilicen sus equivalentes Punycode (nombres IDN). En este caso, para administrar los nombres internacionales en la intranet local, los servidores DNS que se utilizan para la intranet deben admitir la resolución de nombres Unicode.
idn enabled = None
Este valor no convierte ningún nombre de dominio Unicode para que se use Punycode. Este es el valor predeterminado.
La normalización y la comprobación de caracteres se realizan según las últimas reglas de IRI en RFC 3986 y RFC 3987.
El procesamiento de IRI e IDN en la Uri clase también se puede controlar mediante las System.Configuration.IriParsingElementclases de configuración , System.Configuration.IdnElementy System.Configuration.UriSection . El valor System.Configuration.IriParsingElement habilita o deshabilita el procesamiento de IRI en la clase Uri. El valor System.Configuration.IdnElement habilita o deshabilita el procesamiento de IDN en la clase Uri.
El valor de configuración de System.Configuration.IriParsingElement y System.Configuration.IdnElement se leen una vez cuando se construye la primera System.Uri clase. Después, se omitirán los cambios realizados en los valores de configuración.
La clase System.GenericUriParser también se ha ampliado para permitir la creación de un analizador personalizable que admita IRI e IDN. Para especificar el comportamiento de un objeto System.GenericUriParser, se pasa una combinación bit a bit de los valores disponibles en la enumeración System.GenericUriParserOptions al constructor System.GenericUriParser. El tipo GenericUriParserOptions.IriParsing indica que el analizador admite las reglas de análisis especificadas en RFC 3987 para los Identificadores de recursos internacionales (IRI).
El GenericUriParserOptions.Idn tipo indica que el analizador admite el análisis de Nombres de dominio internacionalizados (IDN) de nombres de host. En .NET 5 y versiones posteriores (incluido .NET Core) y .NET Framework 4.5+, siempre se usa IDN. En versiones anteriores, una opción de configuración determina si se usa IDN.
Compatibilidad con la ruta de acceso de archivo implícita
Uri también se puede usar para representar rutas de acceso del sistema de archivos locales. Estas rutas de acceso se pueden representar explícitamente en URI que comienzan con el esquema de file:// y implícitamente en URI que no tienen el esquema de file://. Como ejemplo concreto, los dos URI siguientes son válidos y representan la misma ruta de acceso de archivo:
Uri uri1 = new Uri("C:/test/path/file.txt") // Implicit file path.
Uri uri2 = new Uri("file:///C:/test/path/file.txt") // Explicit file path.
Estas rutas de acceso implícitas de archivo no son compatibles con la especificación de URI, por lo que debe evitarse siempre que sea posible. Cuando se usa .NET Core en sistemas basados en Unix, las rutas de acceso implícitas a archivos pueden ser especialmente problemáticas, ya que una ruta de acceso de archivo implícita absoluta es indistinguible desde una ruta de acceso relativa. Cuando esta ambigüedad está presente, Uri el valor predeterminado es interpretar la ruta de acceso como un URI absoluto.
Consideraciones sobre la seguridad
Debido a problemas de seguridad, la aplicación debe tener precaución al aceptar Uri instancias de orígenes que no son de confianza y establecer dontEscape
true
en en el constructor. Puede comprobar una cadena de URI para comprobar la validez llamando al IsWellFormedOriginalString método .
Al tratar con la entrada de usuario que no es de confianza, confirme suposiciones sobre la instancia recién creada Uri
antes de confiar en sus propiedades.
Esto se puede hacer de la siguiente manera:
string userInput = ...;
Uri baseUri = new Uri("https://myWebsite/files/");
if (!Uri.TryCreate(baseUri, userInput, out Uri newUri))
{
// Fail: invalid input.
}
if (!baseUri.IsBaseOf(newUri))
{
// Fail: the Uri base has been modified - the created Uri is not rooted in the original directory.
}
Esta validación se puede usar en otros casos, como cuando se trabaja con rutas UNC, simplemente cambiando :baseUri
Uri baseUri = new Uri(@"\\host\share\some\directory\name\");
Consideraciones de rendimiento
Si usa un archivo Web.configque contiene URI para inicializar la aplicación, se requiere tiempo adicional para procesar los URI si sus identificadores de esquema no son estándar. En tal caso, inicialice las partes afectadas de la aplicación cuando se necesiten los URI, no a la hora de inicio.