Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Los desarrolladores web requieren la capacidad de describir la forma y el diseño de los URI a los que responden sus servicios. Windows Communication Foundation (WCF) ha agregado dos nuevas clases para conceder a los desarrolladores control sobre sus URI. UriTemplate y UriTemplateTable forman la base del motor de distribución basado en URI en WCF. Estas clases también se pueden usar por su cuenta, lo que permite a los desarrolladores aprovechar las plantillas y el mecanismo de asignación de URI sin implementar un servicio WCF.
Plantillas
Una plantilla es una manera de describir un conjunto de URI relativos. El conjunto de plantillas de URI de la tabla siguiente muestra cómo se puede definir un sistema que recupera varios tipos de información meteorológica.
Datos | Plantilla |
---|---|
Previsión nacional | clima/nacional |
Previsión de estado | tiempo/{estado} |
Previsión de la ciudad | tiempo/{estado}/{ciudad} |
Previsión de actividad | tiempo/{estado}/{ciudad}/{actividad} |
En esta tabla se describe un conjunto de URI estructuralmente similares. Cada entrada es una plantilla de URI. Los segmentos entre llaves describen las variables. Los segmentos que no están entre llaves describen cadenas literales. Las clases de plantilla de WCF permiten que un desarrollador tome un URI entrante, por ejemplo, "/weather/wa/seattle/cycling" y hacer coincidir con una plantilla que lo describa, "/weather/{state}/{city}/{activity}".
UriTemplate
UriTemplate es una clase que encapsula una plantilla de URI. El constructor toma un parámetro de cadena que define la plantilla. Esta cadena contiene la plantilla en el formato descrito en la sección siguiente. La UriTemplate clase proporciona métodos que permiten hacer coincidir un URI entrante con una plantilla, generar un URI a partir de una plantilla, recuperar una colección de nombres de variables usados en la plantilla, determinar si dos plantillas son equivalentes y devolver la cadena de la plantilla.
Match(Uri, Uri) toma una dirección base y un URI candidato e intenta hacer coincidir el URI con la plantilla. Si la coincidencia se realiza correctamente, se devuelve una instancia UriTemplateMatch. El UriTemplateMatch objeto contiene un URI base, el URI candidato, una colección de nombre/valor de los parámetros de consulta, una matriz de los segmentos de ruta de acceso relativa, una colección de nombre/valor de variables que se han coincidido, la UriTemplate instancia utilizada para realizar la coincidencia, una secuencia que contiene cualquier parte no coincidente del URI candidato (se utiliza cuando la plantilla tiene un carácter comodín), y un objeto asociado con la plantilla.
Nota:
La UriTemplate clase omite el esquema y el número de puerto al hacer coincidir un URI candidato con una plantilla.
Hay dos métodos que permiten generar un URI a partir de una plantilla y BindByName(Uri, NameValueCollection)BindByPosition(Uri, String[]). BindByName(Uri, NameValueCollection) toma una dirección base y una colección de parámetros nombre/valor. Estos parámetros se sustituyen por variables cuando la plantilla está enlazada. BindByPosition(Uri, String[]) toma los pares nombre-valor y los sustituye de izquierda a derecha.
ToString() devuelve la cadena de plantilla.
La PathSegmentVariableNames propiedad contiene una colección de los nombres de las variables usadas en los segmentos de ruta de la cadena modelo.
IsEquivalentTo(UriTemplate) toma como UriTemplate parámetro y devuelve un valor booleano que especifica si las dos plantillas son equivalentes. Para obtener más información, consulte la sección Equivalencia de plantillas más adelante en este tema.
UriTemplate está diseñado para trabajar con cualquier esquema de URI que se ajuste a la gramática del URI HTTP. A continuación se muestran ejemplos de esquemas de URI admitidos.
http://
https://
net.tcp://
net.pipe://
sb://
Los esquemas como file:// y urn:// no se ajustan a la gramática del URI HTTP y provocan resultados impredecibles cuando se usan con plantillas de URI.
Sintaxis de cadenas de plantillas
Una plantilla tiene tres partes: una ruta de acceso, una consulta opcional y un fragmento opcional. Para obtener un ejemplo, consulte la plantilla siguiente:
"/weather/{state}/{city}?forecast={length)#frag1
La ruta consta de "/weather/{state}/{city}", la consulta consta de "?forecast={length}", y el fragmento consta de "#frag1".
Las barras diagonales iniciales y finales son opcionales en la expresión de la ruta de acceso. Las expresiones de consulta y fragmento se pueden omitir por completo. Una ruta consta de una serie de segmentos delimitados por '/', donde cada segmento puede tener un valor literal, un nombre de variable (escrito entre {llaves}), o un carácter comodín como un asterisco ('*'). En la plantilla anterior, el segmento "\weather\ es un valor literal mientras que "{state}" y "{city}" son variables. Las variables toman su nombre a partir del contenido de sus llaves y se pueden reemplazar después por un valor concreto para crear un URI cerrado. El carácter comodín es opcional, pero solo puede aparecer al final del URL, donde se corresponde lógicamente con "el resto del trayecto".
La expresión de consulta, si está presente, especifica una serie de pares de nombre/valor sin ordenar delimitados por '&'. Los elementos de la expresión de consulta pueden ser pares literales (x=2) o un par de variables (x={var}). Solo el lado derecho de la consulta puede tener una expresión variable. No se permite que {someName} sea igual a {someValue}. No se permiten valores no emparejados (?x). No hay ninguna diferencia entre una expresión de consulta vacía y una expresión de consulta que consta de un solo "?". (ambos significan "cualquier consulta").
La expresión de fragmento puede constar de un valor literal, no se permiten variables.
Todos los nombres de variables de plantilla dentro de una cadena de plantilla deben ser únicos. Los nombres de las variables de plantilla no distinguen mayúsculas de minúsculas.
Ejemplos de cadenas de plantilla válidas:
""
"/zapato"
"/zapato/*"
"{zapato}/barco"
"{zapato}/{barco}/cama/{colcha}"
"zapato/{barco}"
"zapato/{barco}/*"
"zapato/barco?x=2"
“zapato/{barco}?x={cama}”
"zapato/{barco}?x={cama}&y=banda"
"?x={shoe}"
"shoe?x=3&y={var}
Ejemplos de cadenas de plantilla no válidas:
"{zapato}/{ZAPATO}/x=2" – nombres de variables duplicados.
“{zapato}/barco/?cama={zapato}”: nombres de variables duplicados.
"?x=2&x=3" – Los pares nombre-valor dentro de una cadena de consulta deben ser únicos, incluso si son literales.
"?x=2&" – La cadena de consulta tiene un formato incorrecto.
"?2&x={zapato}": la cadena de consulta debe estar formada por pares nombre-valor.
"?y=2&X=3" – La cadena de consulta debe ser pares de valor de nombre, los nombres no pueden empezar por '&'.
Segmentos de ruta compuestos
Los segmentos de rutas compuestas permiten que un único segmento de URL contenga varias variables, así como variables combinadas con literales. A continuación, se ofrecen ejemplos de segmentos de ruta de acceso compuestos válidos.
/nombreDeArchivo.{ext}/
/{filename}.jpg/
/{filename}. {ext}/
/{a}.{b}algúnLiteral{c}({d})/
A continuación se muestran ejemplos de segmentos de ruta no válidos.
/{} - Las variables deben tener nombre.
/{zapato}{barco}: las variables deben estar separadas por un literal.
Segmentos de trayectos coincidentes y compuestos
Los segmentos de ruta de acceso compuestos permiten definir una UriTemplate que tenga varias variables dentro de un único segmento de ruta de acceso. Por ejemplo, en la siguiente cadena de plantilla: "Addresses/{state}. {city}" dos variables (estado y ciudad) se definen dentro del mismo segmento. Esta plantilla coincidiría con una dirección URL como http://example.com/Washington.Redmond
, pero también coincidirá con una dirección URL como http://example.com/Washington.Redmond.Microsoft
. En este último caso, la variable state contendrá "Washington" y la variable city contendrá "Redmond.Microsoft". En este caso, cualquier texto (excepto '/') coincidirá con la variable {city}. Si desea una plantilla que no coincida con el texto "extra", coloque la variable en un segmento de plantilla aparte, por ejemplo: "Direcciones/{state}/{city}".
Segmentos de carácter comodín con nombre
Un segmento con nombre comodín es cualquier segmento de variable de ruta cuyo nombre de variable comienza con el carácter comodín '*'. La cadena de plantilla siguiente contiene un segmento de carácter comodín con nombre denominado "zapato".
"literal/{*shoe}"
Los segmentos de carácter comodín deben seguir las reglas siguientes:
Puede haber como máximo un segmento comodín nombrado para cada cadena de plantilla.
Un segmento de carácter comodín con nombre debe aparecer en el segmento situado en el extremo derecho de la ruta de acceso.
Un segmento con nombre comodín no puede coexistir con un segmento comodín anónimo dentro de la misma cadena de plantilla.
El nombre de un segmento de carácter comodín con nombre debe ser único.
Los segmentos con nombre comodín no pueden tener valores predeterminados.
Los segmentos con nombre comodín no pueden terminar con "/".
Valores de variable predeterminados
Los valores de variable predeterminados permiten especificar valores predeterminados para las variables dentro de una plantilla. Las variables predeterminadas se pueden definir con los corchetes que declaran la variable o como una colección pasada al constructor UriTemplate. En la plantilla siguiente se muestran dos maneras de especificar con UriTemplate variables con valores predeterminados.
UriTemplate t = new UriTemplate("/test/{a=1}/{b=5}");
Esta plantilla declara una variable denominada a
con un valor predeterminado de 1
y una variable denominada b
con un valor predeterminado de 5
.
Nota:
Solo las variables de segmento de ruta pueden tener valores predeterminados. Las variables de cadena de consulta, las variables de segmento compuesto y las variables con nombre comodín no pueden tener valores predeterminados.
En el código siguiente se muestra cómo se controlan los valores de variable predeterminados al hacer coincidir un URI candidato.
Uri baseAddress = new Uri("http://localhost:8000/");
UriTemplate t = new UriTemplate("/{state=WA}/{city=Redmond}/", true);
Uri candidate = new Uri("http://localhost:8000/OR");
UriTemplateMatch m1 = t.Match(baseAddress, candidate);
Console.WriteLine($"Template: {t}");
Console.WriteLine($"Candidate URI: {candidate}");
// Display contents of BoundVariables
Console.WriteLine("BoundVariables:");
foreach (string key in m1.BoundVariables.AllKeys)
{
Console.WriteLine($"\t{key}={m1.BoundVariables[key]}");
}
// The output of the above code is
// Template: /{state=WA}/{city=Redmond}/
// Candidate URI: http://localhost:8000/OR
// BoundVariables:
// STATE=OR
// CITY=Redmond
Nota:
Un URI como http://localhost:8000///
no coincide con la plantilla enumerada en el código anterior, pero un URI como http://localhost:8000/
sí.
En el código siguiente se muestra cómo se controlan los valores de variable predeterminados al crear un URI con una plantilla.
Uri baseAddress = new Uri("http://localhost:8000/");
Dictionary<string,string> defVals = new Dictionary<string,string> {{"a","1"}, {"b", "5"}};
UriTemplate t = new UriTemplate("/test/{a}/{b}", defVals);
NameValueCollection vals = new NameValueCollection();
vals.Add("a", "10");
Uri boundUri = t.BindByName(baseAddress, vals);
Console.WriteLine("BaseAddress: {0}", baseAddress);
Console.WriteLine("Template: {0}", t.ToString());
Console.WriteLine("Values: ");
foreach (string key in vals.AllKeys)
{
Console.WriteLine("\tKey = {0}, Value = {1}", key, vals[key]);
}
Console.WriteLine("Bound URI: {0}", boundUri);
// The output of the preceding code is
// BaseAddress: http://localhost:8000/
// Template: /test/{a}/{b}
// Values:
// Key = a, Value = 10
// Bound URI: http://localhost:8000/test/10/5
Cuando una variable recibe un valor predeterminado de null
, hay algunas restricciones adicionales. Una variable puede tener un valor predeterminado de null
si la variable está contenida dentro del segmento más derecho de la cadena de plantilla o si todos los segmentos a la derecha del segmento tienen valores predeterminados de null
. A continuación se muestran cadenas de plantilla válidas con valores predeterminados de null
:
UriTemplate t = new UriTemplate("shoe/{boat=null}");
UriTemplate t = new UriTemplate("{shoe=null}/{boat=null}");
UriTemplate t = new UriTemplate("{shoe=1}/{boat=null}");
A continuación se muestran cadenas de plantilla no válidas con valores predeterminados de null
:
UriTemplate t = new UriTemplate("{shoe=null}/boat"); // null default must be in the right most path segment
UriTemplate t = new UriTemplate("{shoe=null}/{boat=x}/{bed=null}"); // shoe cannot have a null default because boat does not have a default null value
Valores predeterminados y coincidencias
Al hacer coincidir un URI candidato con una plantilla que tenga valores predeterminados, los valores predeterminados se colocan en la BoundVariables colección si no se especifican valores en el URI candidato.
Equivalencia de plantillas
Se dice que dos plantillas son estructuralmente equivalentes cuando coinciden todos los literales de las plantillas y tienen variables en los mismos segmentos. Por ejemplo, las plantillas siguientes son estructuralmente equivalentes:
/a/{var1}/b b/{var2}?x=1&y=2
a/{x}/b%20b/{var1}?y=2&x=1
a/{y}/B%20B/{z}/?y=2&x=1
Algunas cosas que hay que tener en cuenta:
Si una plantilla contiene barras diagonales al principio, solo se omite la primera.
Al comparar las cadenas de plantillas para ver la equivalencia estructural, se ignoran las mayúsculas/minúsculas de los nombres de las variables y segmentos de rutas, mientras que sí se tienen en cuenta en las cadenas de consulta.
Las cadenas de consulta no están ordenadas.
UriTemplateTable
La UriTemplateTable clase representa una tabla asociativa de UriTemplate objetos enlazados a un objeto de la elección del desarrollador.
UriTemplateTable debe contener al menos un UriTemplate antes de llamar a MakeReadOnly(Boolean). El contenido de UriTemplateTable se puede cambiar hasta que se llame a MakeReadOnly(Boolean). La validación se realiza cuando se llama a MakeReadOnly(Boolean). El tipo de validación realizado depende del valor del parámetro allowMultiple
a MakeReadOnly(Boolean).
Cuando se llama MakeReadOnly(Boolean) y pasa false
, la UriTemplateTable comprueba que no hay plantillas en la tabla. Si encuentra alguna plantilla estructuralmente equivalente, produce una excepción. Esto se usa junto con MatchSingle(Uri) cuando desea asegurarse de que solo una plantilla coincide con un URI entrante.
Cuando se llama a MakeReadOnly(Boolean) y se pasa true
, UriTemplateTable permite que varias plantillas estructuralmente equivalentes estén contenidas dentro de UriTemplateTable.
Si un conjunto de UriTemplate objetos agregados a una UriTemplateTable contiene cadenas de consulta, no deben ser ambiguos. Se permiten cadenas de consulta idénticas.
Nota:
Aunque el componente UriTemplateTable permite direcciones base que usan esquemas distintos de HTTP, el esquema y el número de puerto se omiten al hacer coincidir las URI candidatas con las plantillas.
Ambigüedad de cadenas de consulta
Las plantillas que comparten una ruta de acceso equivalente contienen cadenas de consulta ambiguas si hay un URI que coincide con más de una plantilla.
Los siguientes conjuntos de cadenas de consulta son inequívocos dentro de sí mismos:
?x=1
?x=2
?x=3
?x=1&y={var}
?x=2&z={var}
?x=3
?x=1
?
? x={var}
?
?m=get&c=rss
?m=put&c=rss
?m=get&c=atom
?m=put&c=atom
Los siguientes conjuntos de plantillas de cadena de consulta son ambiguos dentro de sí mismos:
?x=1
?x={var}
"x=1": coincide con ambas plantillas.
?x=1
?y=2
"x=1&y=2" coincide con ambas plantillas. Esto se debe a que una cadena de consulta puede contener más variables de cadena de consulta que la plantilla con la que coincide.
?x=1
?x=1&y={var}
"x=1&y=3" coincide con ambas plantillas.
?x=3&y=4
?x=3&z=5
Nota:
Se considera que los caracteres á y Á son diferentes cuando aparecen como parte de una ruta URI o literal de segmento de ruta UriTemplate (pero los caracteres a y A se considera que son iguales). Los caracteres á y Á se consideran los mismos caracteres cuando aparecen como parte de una UriTemplate {variableName} o una cadena de consulta (y a y A también se consideran los mismos caracteres).