This article has been localized into Spanish by the community.
Restricciones de ruteo
En el artículo previo de este capítulo, vimos cómo crear plantillas de rutas muy flexibles, para atrapar diferentes tipos de estructuras URL y mapearlas correctamente. Sin embargo, en algún punto tus rutas pueden volverse tan generales o quizás tú solo tienes una estructura muy específica que quieras reforzar. Para esto, ASP.NET MVC ha introducido un claro concepto de restricciones de ruteo, permitiéndote ser mucho más específico cuando defines los parámetros de tus rutas.
Para ilustrar como las restricciones de ruteo pueden ayudar, tomemos un vistazo al ejemplo del artículo previo, donde creamos una ruta para manejar el escenario clásico ID/UrlSlug:
[Route("blog/{entryId}/{slug}")]
public IActionResult Blog(int entryId, string slug)
{
return Content($"Blog entry with ID #{entryId} requested (URL Slug: {slug})");
}
Hay varios tipos de restricciones de rutas, entonces utilizaremos este ejemplo para ver cómo trabajan todas ellas.
Restricciones de tipo de dato
En este caso, usamos un entero para el parámetro entryId, para que podamos también aplicar eso directamente en la plantilla, usando la sintaxis especial de restricción de rutas:
[Route("blog/{entryId:int}/{slug}")]
public IActionResult Blog(int entryId, string slug)
{
....
La diferencia puede ser encontrada en el parámetro de la ruta, donde agregado un :int como esto: {entryId:int}. Ahora la url solamente se relacionaran con la ruta sigue el parámetro entryId es un entero, como esto:
/blog/153/testing-the-system/
Las URLs como ésta ya no coincidirán:
/blog/abc153def/testing-the-system/
Tipos de restricciones de tipo de datos
La restricción de tipo de dato int es desde luego sólo una de muchas. Aquí hay ejemplos de otros limitantes de tipo de dato los cuales puedes usar en tus rutas:
- {entryId:int}
- {isVisible:bool}
- {entryDate:datetime}
- {weight:double}
- {weight:float}
- {price:decimal}
- {id:guid}
- {postId:long}
Restricciones de longitud y Rango
Otros tipos de restricción de ruta te ayudará aplicar una cierta longitud mínima y/ máxima para cadenas, un valor mínimo/ máximo para tipos numéricos. Podemos usar eso para hacer a nuestra plantilla de ruta de antes aún más específica. Por ejemplo, ya que el entryId debería corresponder a un registro de base de datos, podemos sostener que el valor debe de ser más grande que cero. Podemos usar la restricción min para hacer eso:
[Route("blog/{entryId:min(1)}/{slug}")]
public IActionResult Blog(int entryId, string slug)
{
....
Si sabemos que hay un valor máximo, podemos usar la restricción max, la cual funciona justo como la restricción min, o, si hay tanto un valor mínimo como uno máximo, podemos usar la restricción range:
[Route("blog/{entryId:range(1, 999999)}/{slug}")]
public IActionResult Blog(int entryId, string slug)
{
....
También queremos evitar cadenas vacías para el parámetro slug - de hecho, ya que el slug está basado en el título del post del Blog en nuestro escenario, podemos sostener que el slug nunca debería ser más corto que 3 caracteres. Podemos usar la restricción minlength para esto:
[Route("blog/{entryId:range(1, 999999)}/{slug:minlength(3)}")]
public IActionResult Blog(int entryId, string slug)
{
....
En el caso que lo necesites, desde luego que también hay una restricción de maxlength e incluso una restricción length- la primera especifica una longitud máxima, mientras que la segunda fuerza una cadena de una longitud específica, por ejemplo length(8) solamente acepta una cadena de exactamente 8 caracteres.
Combinar múltiples restricciones
Con todo mente, creo que es buena hora de ilustrar un detalle importante sobre las restricciones de ruta: pueden ser fácilmente combinadas. Por ejemplo, tú puedes requerir tanto como un tipo de dato específico así como una longitud mínima, o tú puedes incluso unir múltiples restricciones de longitud. Simplemente separa cada restricción con un carácter: (dos puntos), como esto:
[Route("blog/{entryId:int:range(1, 999999)}/{slug:minlength(3):maxlength(50)}")]
public IActionResult Blog(int entryId, string slug)
{
....
Con esto en su lugar, parámetro tiene que ser de tipo de dato entero y debe de estar entre 1 y 999999. El segundo parámetro por defecto es una cadena, ya que el tipo de dato no está especificado, y tiene que ser al menos de 3 caracteres de largo pero no mayor a 50 caracteres.
Restricciones con expresiones regulares
Cuando necesitas aún más control sobre cómo pueden verse aceptables los parámetros, puedes usar expresiones regulares. Ellas te permiten especificar un patrón muy preciso, usando todas las extremadamente poderosas herramientas de comparación de texto encontradas en la sintaxis de expresiones regulares. De hecho, las expresiones regulares son un gran tópico en sí mismas, así que la sintaxis no será cubierta en este artículo, pero desde luego te enseñaré cómo usar una expresión regular en una restricción de ruta en ASP.NET MVC.
Inspirado por nuestro ejemplo de URL slug usado bastante en los ejemplos de arriba, podemos decidir que nuestra parte de entry ID y slug no deben ser parámetros separados - en su lugar, queremos combinarlos en una cadena más natural, permitiéndonos una URL cómo está:
/blog/153-testing-the-system/
Si aún queremos que la primera parte sea un entero, permitiéndonos encontrar el post deseado en la base de datos con el ID, entonces creamos una expresión regular para corresponder a este tipo de URL:
^[0-9]{1,7}\-[a-z0-9\-]{3,50}$
Si no sabes expresiones regulares, es probable que esto luzca para ti incomprensible, pero pégate a mí De cualquier forma. De acuerdo a esta expresión regular, necesitamos una cadena que empiece con un número, con una longitud mínima de 1 y una longitud máxima de 7 (longitud de la cadena correspondiente, por ejemplo 9999999). Después de eso, un guión debe ocurrir y luego una cadena consistente de letras, números y guiones solamente, con una longitud mínima de 3 y una longitud máxima de 50. Ahora solamente podemos aplicar esto a nuestra ruta, usando la restricción regex():
[Route(@"blog/{slug:regex(^[[0-9]]{{1,7}}\-[[a-z0-9\-]]{{3,50}}$)}")]
public IActionResult Blog(string slug)
{
....
Notarás que la expresión regular luce un poco diferente que antes junto porque la restricción de la ruta en su sintaxis usa caracteres especiales como { y [, los cuales También tienen un significado especial en una expresión regular, son escapados al ponerlos doble.
Ahora en un método, puedes usar técnicas de separación en cadenas simples para separar la parte del identificador de la parte del slug y luego traer y Mostrar el post correcto. Aquí hay un ejemplo:
[Route(@"blog/{slug:regex(^[[0-9]]{{1,7}}\-[[a-z0-9\-]]{{3,50}}$)}")]
public IActionResult Blog(string slug)
{
int hyphenPos = slug.IndexOf("-");
int entryId = int.Parse(slug.Substring(0, hyphenPos));
string slugPart = slug.Substring(hyphenPos + 1);
return Content($"Blog entry with ID #{entryId} requested (URL Slug: {slug})");
}
Así que, usando el poder de las expresiones regulares, puedes aplicar incluso los patrones más complejos de URL para tus Rutas.
Resumen
Aplicando restricciones a sus rutas obtienes más control sobre cuando una uRL corresponde a una ruta en específico. Esto es especialmente útil si tú tienes ruta similares, las cuales podrían interferir una con otra. Aplicando las restricciones o limitaciones de rutas a una o varias de estas frutas puedes tener más control sobre Cuál ruta corresponde a varias urls.