Nombres de algunos controladores distintos en ASP.NET MVC

Hola! Un post para comentaros como he implementado una cosilla que necesitaba en ASP.NET MVC (v1). En concreto necesitaba mapear las URLs de tipo /api/{controller}/{action} al controlador especificado, pero con la salvedad de que el nombre del controlador empezaba por War. Es decir la URL /api/Foo/Index debía llamar a la acción del controlador WarFoo (en lugar del controlador Foo).

En resumen lo que quería era:

/Foo/Index –> Llamar a acción Index del controlador Foo

/api/Foo/Index –> llamar a acción Index del controlador WarFoo

/api/WarFoo/Index –> Llamar a acción Index del controlador WarFoo

La primera de las reglas se cumple fácilmente con la definición estándard de la tabla de rutas de MVC:

routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);

Para dar soporte a las otras dos reglas me he creado un RouteHandler propio…

¿Que son los RouteHandlers?

Los RouteHandlers son clases que implementan la interfaz IRouteHandler y que son las encargadas de procesar las peticiones que vienen via una ruta (casi todas en el caso de MVC). Generalmente un RouteHandler lo que hace es crear un IHttpHandler que procese la petición enrutada. ASP.NET MVC viene con un RouteHandler por defecto (MvcRouteHandler) que termina creando un IHttpHandler por defecto (MvcHandler) que es el que crea el controlador asociado y le cede el control. En mi caso el comportamiento de MvcHandler ya me va bien: no quiero cambiar la política de creación de controladores ni nada, solo quiero añadir el prefijo “War” al controlador.

Por suerte, ASP.NET MVC es muy extensible y nos lo pone realmente fácil para añadir un RouteHandler propio: basta con crearlo y vincularlo con una ruta que tengamos en la tabla de rutas.

Veamos primero como vincularíamos nuestro RouteHandler (que he llamado WarRouteHandler) con una ruta, usando el método Add de la tabla de rutas:

routes.Add(new Route("api/{controller}/{action}/{id}",
new RouteValueDictionary(
new { controller = "Home", action = "Index", id = "" }),
new WarRouteHandler())
);

El primer parámetro es la URL de la ruta, el segundo los valores de la ruta (a diferencia del método MapRoute que acepta un objeto anónimo para esto, aquí nosotros debemos crear específicamente el RouteValuesDictionary) y finalmente el RouteHandler a utilizar!

Nota: Para que todo funcione bien, esta segunda ruta debe estar en la table de rutas antes que la ruta anterior. Más detalles en el post continuación de este!

Ya casi estamos: Sólo nos falta crear el RouteHandler, para ello creamos una clase que implemente IRouteHandler, y en el método GetHttpHandler (que es el único) vamos a añadir “War” al nombre del controlador. Para saber el nombre del controlador nos basta con acceder a los valores de la ruta (RouteData.Values) donde están todos (controlador, acción, id y otros adicionales que hubiesen). El código es simple:

public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
string controller = requestContext.RouteData.Values["controller"].ToString();
if (!controller.ToLowerInvariant().StartsWith("war"))
{
requestContext.RouteData.Values["controller"] = string.Format("War{0}", controller);
}

return new MvcHandler(requestContext);
}

Ahora ya tenemos las URLs de tipo /api/{controlador} enrutadas al controlador War{controlador}.

Un saludo!

Nota: Este post no está completo. Si te interesa el tema lee la continuación, puesto que no todo es tan fácil!

4 comentarios sobre “Nombres de algunos controladores distintos en ASP.NET MVC”

  1. Hablando de Asp.net MVC.
    Dentro de Patterns & Practices existen una serie de herramienas muy útiles, personalmente me he ‘aficionado’ mucho a la Enterprise library. Ahora que doy mi salto del escritorio a la web estoy mirando que opcione tengo… como siempre el campo es muy extenso, pero me llama la atención el uso del Web Service Sw Factory, pero una vez más mi ceguera mental me impide ver sí existe una posible relacción o integración de esta herramienta con Asp.net MVC

    Me puedes ayudar?

    Gracias.

  2. @Galcet,
    No conozco mucho la Web Service Sw Factory, pero por lo que se son guías y ayuda para la construcción de servicios web.
    ASP.NET MVC no está pensada para la creación de servicios web, está pensada para la creación de aplicaciones web. Si MVC se puede comparar con alguna otra tecnología dentro del mundo MS es con Webforms.
    Mucha gente confunde ASP.NET con Webforms, pero no es lo mismo: ASP.NET es una tecnología y Webforms es un framework para la creación de aplicaciones web en esta tecnología… Bien, pues MVC es otro framework. Pero también es ASP.NET esto significa que todo lo que da la tecnología (p.ej. autenticación, cache, roles, …) lo comparten.
    Ya te digo, no conozco la Service Sw Factory, pero entiendo que una situación normal seria usarla para crear tus servicios web, y usar mvc (o webforms) para crear la aplicación web si la hubiera.

    Un saludo y gracias por tu comentario!!! 🙂

Responder a anonymous Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *