Hoy os traigo un pequeño Tip que a priori puede ser un poco tonto pero que a más de uno le puede salvar de horas de modificar código o de buscar la aguja en el pajar.
Escenario
Tenemos una aplicación ASP.NET MVC que tiene, dentro de las vistas, llamadas “Ajax” a acciones de la propia aplicación MVC, lo que implicará que tengamos puesto “a fuego” el controlador que queremos llamar.
Ejemplo:
$.ajax({ url: "/MyController/MyAction", data: { id: myId }, type: "GET" }).done(function(){ alert('DONE!!'); });
NOTA: Siempre hay otras formas de hacerlo más elegante.
Problema
Qué ocurriría si:
- Cambiamos la acción a otro controlador
- Cambiamos el nombre del controlador
- Usamos la gran herramienta de todo developer “Copy/Paste” y ponemos este método en otras vistas de otros controladores
- …
Bueno, para todas las opciones, lo que ocurre es que tendremos que estar atentos de cambiar el controlador en la “url” que estamos usando en la llamada “ajax” y esto a veces se nos puede pasar por alto y tenernos un buen rato buscando la solución al problema de que de repente no nos funcione nuestra llamada.
Solución
Puede haber muchas soluciones, unas más elegantes que otras como por ejemplo he visto el tener un fichero de recursos con las acciones y sus “url” correctas lo que nos permitiría tener centralizadas todas las posibles llamadas que hagamos y tan sólo tendríamos que pasarle desde el controller las acciones que va a llamar la vista. Pero no es eso lo que yo voy a exponer, sino que en este caso quiero explicar cómo hacer referencia al controlador actual desde la propia vista, con lo que nos ahorraríamos los problemas de un cambio en el controlador.
¿Y cómo conseguimos saber el controlador actual? Pues con una sencilla línea de código.
@HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString()
Con esto, nuestra llamada Ajax podría quedar de la siguiente forma:
$.ajax({
url: '@Url.Action(“MyAction”, HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString())'
data: { id: myId }, type: "GET" }).done(function(){ alert('DONE!!'); });
NOTA: A algunos os podrá extrañar ver el código “razor” dentro de un bloque JavaScript… ¿funcionará? La respuesta es que sí, puesto que razor es capaz de identificar casi siempre el código de que le corresponde después de una @, lo que nos permite hacer cosas tan “fascinantes” y productivas como esta. Pero tened cuidado con no abusar que al final puede ser peor el remedio que la enfermedad.
Solución mejorada
Debemos intentar evitar la referencia binaria a HttpContext.Current siempre que se pueda y acceder a los route values a través de PageContext, con lo que nuestro código nos quedaría de la siguiente forma:
$.ajax({
url: '@Url.Action("MyAction", PageContext.Page.Request.RequestContext.RouteData.Values["controller"].ToString())',
data: { id: myId },
type: "GET"
}).done(function(){
alert('DONE!!');
});