> Manuales > Manual del framework ASP.NET MVC

Segunda parte de las explicaciones relativas a la tabla de rutas de ASP.NET MVC, un componente básico que podemos configurar para personalizar totalmente las URLs de las aplicaciones web.

Valores de ruta y controladores

Hemos visto que hay dos valores de ruta (“controller” y “action”) que deben ser establecidos a partir de cada URL. Pero… ¿qué ocurre con el resto de valores de ruta que establecemos? (como p.ej. el “id” o el “author" de los ejemplos anteriores). Pues, simplemente, esos valores son pasados a los controladores, donde pueden ser consultados de varias formas, siendo una de las más comunes que estén como parámetros en las acciones.

P.ej. en el caso del valor de ruta author, la acción View del controlador Profile podría estar declarada tal y como sigue:

public class ProfileController : Controller
{
[ActionName("View")]
public ActionResult Ver(string author)
{
return View();
}
}

Nota: En este caso usamos el atributo [ActionName] que permite indicar el nombre de la acción que implementa un método en concreto. Si no se usa ese atributo el nombre de la acción es el mismo que el nombre del método. En este caso debemos usarlo porque la acción se llama View, pero el nombre de método View ya está definido dentro de la clase Controller (y se usa para devolver vistas).
Podemos ver como la acción View recibe el parámetro “author", cuyo valor será valor de ruta con el mismo nombre (autor). Es decir, en el caso de la URL http://servidor/Ver/Edu el valor del parámetro author será precisamente “Edu”.

En el caso de parámetros opcionales, la cosa es un pelín más delicada. Supongamos que tenemos la siguiente acción:

public class HomeController : Controller
{
public ActionResult Index(int i)
{
return View();
}
}

Supongamos que esta acción se ha mapeado a partir de la entrada “Default” de la tabla de rutas. Si entramos una url del tipo http://servidor/Home/Index/10 no hay problema porque el valor de “id” es 10. Pero, en este caso id es un parámetro opcional, y que ocurre si entramos la URL http://servidor/Home/Index?

Recordad que un parámetro opcional, si no aparece simplemente no se crea. No es que valga 0 ó “” o null. Es que no se crea. Por lo tanto si entramos una URL de tipo http://servidor/Home/Index recibiremos un error:

El error viene a decir que la acción espera un parámetro (id) pero que no hay valor de ruta del cual tomar ese parámetro. Si el parámetro aceptase null (es decir, fuese un valor por referencia como string) el framework asignaría null a ese parámetro y no se quejaría. Pero int no acepta null, así que el framework da ese error.

Es normal, al principio, pensar que para solucionar esto bastaría con añadir, un método Index sin parámetros al controlador. Algo como:

public class HomeController : Controller
{
// URLs tipo /Home/Index/10
public ActionResult Index(int i)
{
return View();
}

// URLs tipo /Home/Index
public ActionResult Index()
{
return View();
}
}

Pero si probamos esto, nos damos cuenta de que ahora nos aparece otro error distinto:

Además ese error aparece indistintamente, ya sea que entremos http://servidor/Home/Index/10 (con id) o http://servidor/Home/Index (sin id).

La razón de este error es muy simple: una misma acción sólo puede ser implementada por un solo método (hay una excepción a este caso que es cuando se usan verbos http distintos, pero eso lo veremos en artículos posteriores). En este caso tenemos dos métodos (Index() y Index(int)) que ambos implementan la acción Index. Y eso no está permitido.

La solución a todo “ese lío” pasa por hacer una de esas dos cosas:

  1. Convertir el parámetro de la acción a algo que acepte nulls (p.ej. string o bien int?).
  2. O modificar la tabla de rutas para que el parámetro en lugar de ser opcional, tenga un valor por defecto.
Si optamos por el primer caso, la acción puede quedar como:

public class HomeController : Controller
{
public ActionResult Index(int? id)
{
return View();
}
}

Ahora, la URL http://servidor/Home/Index se enruta a esta acción y como el valor de ruta id no existe, el método de acción recibirá un null.

Por otro lado la URL http://servidor/Home/Index/10 se enruta a esta misma acción y el valor de ruta id valdrá 10 (y ese será el valor del parámetro que reciba el controlador).

Si optamos por modificar la tabla de rutas, en lugar de declarar el valor de ruta id como opcional, dicho valor debe tener un valor por defecto:

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Home", action = "Index", id = 0} // Parameter defaults
);

Fijaos ahora que el valor por defecto del valor de ruta id es 0. Ahora la URL http://servidor/Home/Index se enruta a la acción con el valor de ruta id con valor 0. Y por su lado la URL http://servidor/Home/Index/20 se enruta a la misma acción pero con el valor de ruta id a 20.

Debe notarse que en este caso no puede diferenciarse entre la url http://servidor/Home/Index y la url http://servidor/Home/Index/0 (ambas URLs tienen el valor de ruta id con valor 0).

Así terminamos este artículo dedicado a la tabla de rutas, uno de los componentes básicos de ASP.NET MVC pero que muy poca gente le presta atención al principio!

Eduard Tomàs

Apasionado de la informática, los videojuegos, rol y... la cerveza. Key Consulta...

Manual