2012-04-11 6 views
11

Al leer acerca de mcv3 me encontré con un nombre de atributo llamado [ActionName]. De hecho, le da un nuevo nombre al método de acción. Probé un escenario que me hizo pensar; ¿Cómo funcionan las partes internas? Cuando tengo los siguientes dos métodos de acción en mi clase controladorAtributo MVC3 ActionName, su comportamiento y efectos

[ActionName("Test")] 
public ActionResult Index() 
{ 
     return View(); 
} 
[ActionName("Index")] 
public ActionResult Test() 
{ 
     return View(); 
} 

pensé que esto va a terminar en una especie de bucle infinito o dará alguna excepción ambigüedad. Pero lo mismo funciona bien y se llama al segundo método cuando doy esta url http://mysite:1234/mycontroller

¿Qué hizo que el motor MVC eligiera el segundo método y no el primero?

¿Alguna idea de por qué sucede esto?

Respuesta

17

Phil Haack tiene un post sobre este asunto: How a method becomes an action

En resumen: la ControllerActionInvoker utiliza la reflexión para encontrar un método coincide con el nombre de la acción.

ActionNameAttribute redefine el nombre del método.

También tenga en cuenta que el nombre de la vista coincide con el ActionName, no el MethodName: el método del índice buscará una vista con el nombre de "Prueba"

+0

ok, excelente publicación. Desde el post, lo que obtengo es que el mago es ControllerActionInvoker. Esto leerá los datos (de la clave "acción") del diccionario de datos de la ruta. Obtendrá un valor de cadena. Y luego buscará primero el nombre de acción y luego el nombre del método. – thinkmmk

+0

@thinkmmk No buscará el método, busca la 'acción'. No usar los resultados de ActionNameAttribute en: method = action –

+0

@AndrewF Si no tengo ningún atributo ActionName sobre mis métodos, entonces supongo que ControllerActionInvoker buscará el nombre de Methods a través de la reflexión en mi clase de controlador. o ¿mvc pone el atributo de nombre de acción por sí mismo si no está presente? – thinkmmk

8

Esta es la magia del Routing engine. En algún lugar dentro de los global.asax.cs el archivo no habría patrones de enrutamiento definidas, en su mayoría que por defecto es

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

Este es un patrón de enrutamiento definido para su aplicación. El atributo de nombre de acción se correlaciona con el parámetro 'acción' dentro de la colección de parámetros (tercer parámetro para MapRoute).

En su caso, si asigna la acción 'Índice' al método 'Prueba'. Debería llamar al método Test(). No estoy seguro de si todavía está llamando a Index() por usted. De hecho, el motor de enrutamiento no se preocupa por el nombre del método si encuentra el atributo ActionName sobre su método público.

+0

Hola Chandermani, Gracias y Sí, tengo las líneas de arriba en mi archivo global.asax. Y edité mi pregunta, sí, llama al método Test(). Entonces, lo que entiendo de su explicación es que esta es la magia del motor de enrutamiento. Y dará preferencia al atributo ActionName en lugar del nombre del método real si encuentra nombres duplicados. Una cosa más, ¿dónde está teniendo lugar esta decisión, es decir, dentro de la fase de Enrutamiento o en la fase de Acción de Control del ciclo de vida? – thinkmmk

+0

Si miras la ruta new {controller = "Home", action = "Index", id = ""}. El motor de enrutamiento decide, el controlador, la acción (de ahí el método en el controlador), y luego el control pasa al método del controlador. – Chandermani

1

ActionNameAttribute que representa un atributo que se utiliza para el nombre de una acción. Si no está presente, se usa el nombre del método.

Cuestiones relacionadas