Este artículo proviene de un motor de traducción automática.

table.one { table-layout:fixed;width: 600px; font-size: 14px; color: #333; margin-bottom: 5px; } table.two { table-layout:fixed;width: 600px; border-top: 3px; border-top-color: #0569b5; border-top-style:solid; margin-bottom: 10px; } .tdwidth{ width:340px; } .tdwidth1{ width: 220px; } tr.fig {background-color:white; color: 00599d; padding: 7px; font-weight:bold; vertical-align:top; } tr.dark td { background-color: #e2f4fd; color: black; padding: 7px; vertical-align:top; } tr.lite td { background-color: #fffcd6; color: black; padding: 7px; vertical-align:top; } .SidebarInsights { width: 560px; height: 465px; float: left; border: 2px solid #008080; padding: 10px 20px 20px 20px; background-color: #e1e8f5; margin: 10px 0px 10px 0px; font-family: Verdana, Arial; font-size: 12px; padding-bottom: 7px; line-height: 16px; color: #333333; }

ASP.NET extremos

La duración Y horas de un controlador de MVC de ASP.NET

Scott Allen

Descarga de código de la Galería de código de MSDN
Examinar el código en línea

Este artículo se basa en una versión preliminar del marco de MVC de ASP.NET.Detalles están sujetos a cambios.

Contenido

Responsable de todas las rutas para una fábrica
Extensibilidad de fábrica
Ejecución es sólo el principio
Selector de atributos
Filtrar atributos
Filtros de acción personalizada
Obtención de resultados
La acción es a través de

Los controladores son los lynchpins del patrón de diseño del controlador de vista de modelo (MVC).Están en la línea de solicitudes de cliente, en primer lugar recibir solicitudes de un cliente y, a continuación, traducir las solicitudes en instrucciones para el modelo donde residen la lógica de dominio de la aplicación y los datos.Los controladores también son responsables de seleccionar una vista para presentar información al usuario.

En este artículo, se analizar minuciosamente el marco ASP.NET MVC y observe cómo funcionan los controladores.Explicaré cómo en que el marco de trabajo interactúa con los controladores y cómo pueden influir en esas interacciones.Veremos las fábricas de controlador, controlador de acciones, filtros de acción y los resultados de acción.

Le cavar muy profundamente en, por lo que si está buscando una introducción más general al marco de MVC de ASP.NET, vea artículo de Carlos Tavares"Creación de aplicaciones sin formularios Web Forms Web."

Responsable de todas las rutas para una fábrica

Es difícil de hablar acerca de la vida de un controlador sin hablando de rutas.La tabla de enrutamiento en una aplicación ASP.NET contiene la información necesaria para el módulo de enrutamiento de ASP.NET extraer información de una dirección URL entrante y dirigir la solicitud para el componente de software adecuado.En columna de enero, examinó utiliza el módulo de enrutamiento de ASP.NET con formularios Web Forms "Distribución con ASP.NET Web Forms".) En esa columna, creé mi propio controlador de enrutamiento para ejecutar un formulario Web, pero el marco ASP.NET MVC proporciona un controlador de enrutamiento que finalmente se dirige una solicitud a uno de nuestros controladores.

Para que este controlador de enrutamiento procesar las solicitudes de MVC, deberá configurar la tabla de enrutamiento durante el inicio de la aplicación.La configuración de enrutamiento predeterminada proporcionada por la plantilla de proyecto MVC reside en el archivo global.asax y se muestra en la figura 1 .

Figura 1 la configuración de ruta predeterminada

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

}

protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);
}

Una de las entradas de configuración de enrutamiento en la figura 1 es una ruta denominado nombre predeterminado con una plantilla de dirección URL de " {controlador} o {acción} o {id} ". Esta plantilla de dirección URL es una trama que el motor de enrutamiento se usar para ver primero si una dirección URL entrante una coincidencia para este enrutamiento. Una dirección URL que coincidirá con una ruta de este tipo sería http://localhost/home/index/. Cuando el motor de enrutamiento encuentra una coincidencia, nuevo utilizará la plantilla de dirección URL como una trama para levante parámetros de la dirección URL entrante. En este ejemplo, la cadena "principal" se convierte en el parámetro del controlador porque es en la posición {controlador}, y la cadena "índice" se convierte en el parámetro de acción.

El objeto de forma anónima con construido como tercer parámetro a MapRoute representa los valores predeterminados para el motor de enrutamiento para utilizar si no encuentra un parámetro determinado en la dirección URL. En el caso de http://localhost/home/index/, el motor de enrutamiento no encontrar información de "ID" en la dirección URL, pero todavía pasará a lo largo de un parámetro de identificador con el valor predeterminado de una cadena vacía. El motor de enrutamiento pasa todos estos parámetros a un controlador de enrutamiento a través de un objeto RouteData.

Es importante tener en cuenta que el motor de enrutamiento sabe nada sobre ASP.NET MVC. Sólo trabajo el motor es analizar direcciones URL y pasar el control a un controlador de ruta. El método de MapRoute que se invoca dentro del método RegisterRoutes de la figura 1 es un método de extensión que se proporcionado por el marco MVC. Cada ruta registrado con MapRoute está configurado para utilizar un objeto MvcRouteHandler, esto es el controlador de ruta proporcionado por el marco MVC. Como hemos visto en la columna enero, es de trabajo el controlador de ruta buscar un controlador HTTP de una solicitud, es un objeto que implementa la interfaz de IHttpHandler. En las aplicaciones de MVC, este objeto será un objeto de tipo MvcHandler y, dentro de MvcHandler es donde se convierte procesamiento en interesante.

Figura 2 muestra el flujo de proceso para una solicitud MVC típica. Cuando control alcanza el MvcHandler, la MvcHandler es capaz de extraer el parámetro del controlador del RouteData generado por el módulo de enrutamiento anteriormente en el procesamiento. El controlador, en última instancia, enviará este parámetro de controlador, que es un valor de cadena, a una fábrica de controlador. Es, a continuación, la responsabilidad de la fábrica para crear y devolver un controlador. Todos los controladores de una aplicación de MVC implementan la interfaz IController.

fig02.gif

La Figura 2 flujo de control para una solicitud de MVC estándar

El marco MVC proporciona una fábrica de controlador de predeterminado (denominado acertadamente DefaultControllerFactory) que se buscan todos los ensamblados en un dominio de aplicación busca todos los tipos que implementan IController y cuyo nombre termina con el controlador. Por lo tanto, si dice la fábrica para buscar un controlador de "inicio", la fábrica puede devuelva una instancia recién instancia de una clase HomeController independientemente de su espacio de nombres o el ensamblado encuentra en, siempre que implementa IController. Este comportamiento es parte del estilo de la MVC "convención sobre configuración". Hay más que el artículo de fábrica, pero vamos a terminar en primer lugar con el procesamiento MvcHandler.

Una vez que el MvcHandler tiene una referencia IController de fábrica, invoca al ejecutar en el controlador y espera el controlador para trabajar su magia. Cuando ejecución finalice, el MvcHandler comprobará si el controlador implementa la interfaz IDisposable y si es así, se llamará Dispose en el controlador para limpiar recursos no administrados.

Extensibilidad de fábrica

La fábrica de controlador es un punto clave de extensibilidad en el marco ASP.NET MVC. Aunque la fábrica predeterminado proporcionada por el marco de trabajo puede buscar un HomeController en cualquier parte de la solución, sólo puede realizar la HomeController si proporciona un constructor sin parámetros. Esta limitación es un problema para los equipos que siga el principio de inversión de dependencia y insertar las dependencias de un controlador a través de su constructor. Como ejemplo, considere la EmployeeController (que se muestra en la figura 3 ), que requiere que alguien para pasar de un componente de registro a su constructor sólo.

La figura 3 EmployeeController

public class EmployeeController : IController
{
    public EmployeeController(ILogger logger)
    {
        _logger = logger;
    }

    public void Execute(RequestContext requestContext)
    {
        // ...
    }

    ILogger _logger;
}

Afortunadamente, puede crear un generador personalizado. Cualquier clase que implementa la interfaz IControllerFactory es un candidato y sólo necesite implementar métodos CreateController y ReleaseController. Sin embargo, la inversión de control de contenedores como StructureMap, unidad, Ninject y Windsor del proyecto Castle están fácilmente disponibles y una perfecta ajuste para este escenario. De hecho, el Proyecto de MVC Contrib en CodePlex incluye implementaciones de IControllerFactory de todos los contenedores enumerados anteriormente.

Si desea utilizar StructureMap como la inversión de control contenedor, puede hacer referencia a los ensamblados StructureMap y MvcContrib.StructureMap, luego escribir el código que se muestra en la figura 4 . El método de InitializeContainer en este listado en primer lugar indica StructureMap para utilizar un tipo SqlServerLogger siempre que sea necesario un ILogger. El código, a continuación, establece el generador de controlador de la aplicación completa mediante el método SetControllerFactory de la ControllerBuilder actual. Durante el procesamiento de solicitud, el MvcHandler se pedir esta misma ControllerBuilder la fábrica configurada actualmente y trabajar con un StructureMapControllerFactory en lugar de la fábrica de marco de trabajo predeterminada.

Contenedor de inicializar la figura 4

protected void Application_Start()
{
    InitializeContainer();
    RegisterRoutes(RouteTable.Routes);
}

private void InitializeContainer()
{
    StructureMapConfiguration
        .ForRequestedType<ILogger>()
        .TheDefaultIsConcreteType<SqlServerLogger>();

    ControllerBuilder.Current.SetControllerFactory(
        new StructureMapControllerFactory());
}

El StructureMapControllerFactory desde el proyecto de MVC Contrib hereda de predeterminado controlador fábrica el marco MVC y seguirá utilizando la convención que describí anteriormente al buscar tipos de controlador para crear una instancia de. Sin embargo, la fábrica utilizará StructureMap para crear una instancia del controlador, y StructureMap sabe cómo trabajar con constructores parametrizados. La configuración que se muestra en la figura 4 sería todo lo que necesita para procesar una solicitud para http://localhost/Employee/. StructureMap creará instancias de la EmployeeController de la figura 3 pasando una referencia SqlServerLogger.

fig05.gif

La figura 5 jerarquía de clases

Ejecución es sólo el principio

Anteriormente indica que el MvcHandler invoca método de ejecución del controlador, espera a que y, a continuación, limpia. Esto se debe a la MvcHandler sólo sabe acerca de los controladores a través de una interfaz IController. Si desea escribir la aplicación en este nivel, puede simplemente derivan todos los controladores de la interfaz IController y proporcionar una implementación del método Execute. Sin embargo, el marco de MVC ASP.NET ofrece un modelo más rico de ejecución de controladores a través de la jerarquía de clases que se muestra en la figura 5 .

De forma predeterminada, los controladores que se agrega a un proyecto de MVC ASP.NET derivan de la clase de System.Web.mvc.Controller. Una forma para agregar un nuevo controlador es haga clic con el botón secundario en la carpeta de controladores en el Explorador de soluciones y seleccione Agregar | controlador, que le ofrece el cuadro de diálogo mostrado en la figura 6 . Recuerde que, de la fábrica de controlador encontrar el controlador en que el nombre debe acabar con el controlador.

La clase base de controlador presenta el concepto de una acción. Las acciones son métodos en el controlador que sirven como el destino final de la solicitud en una aplicación de MVC. Anteriormente, señalar que el módulo de enrutamiento de ASP.NET se levante fuera "principal" como parámetro de controlador de una dirección URL de http://localhost/home/index/. Esta información es suficiente para enrutar la solicitud del controlador adecuado. El módulo de enrutamiento también seleccionado fuera "índice" como un parámetro de acción. Cuando la MvcHandler indica el HomeController que se va a ejecutar, es la lógica compuesta dentro de la clase de controlador de base para inspeccionar este parámetro de acción e invocar el método de controlador adecuado. La mayor parte de esta lógica de enrutamiento de acción que se encuentra dentro de la clase ControllerActionInvoker pública.

fig06.gif

Figura 6 agregar del controlador

la figura 7 es el HomeController proporcionada por la plantilla de proyecto ASP.NET MVC. El público métodos, índice de la instancia y adicional sobre, representan las acciones que el marco de trabajo llamará a cuando el cliente solicita principal o índice o y casa aproximadamente /, respectivamente. Cualquier método de instancia público puede servir como una acción de controlador siempre que el marco de trabajo puede determinar para determinados que la acción es la acción correcta que se va a invocar (en otras palabras, ser cuidado con la sobrecarga de métodos). Hay reglas adicionales de reproducción al marco de trabajo está buscando una acción que se va a invocar. Puede influir en elegir el marco acciones, establecer reglas adicionales de selección de acción y manipular el comportamiento de las acciones mediante atributos.

La figura 7 HomeController

[HandleError]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }

    public ActionResult About()
    {
        return View();
    }
}

Selector de atributos

Se puede decorar una acción de controlador con atributos de selector para proporcionar la información adicional de marco de trabajo para tener en cuenta al que es seleccionar una acción que se va a invocar.Por ejemplo, agregar un atributo [NonAction] a un método controlador harán que el método se excluirá de la lista de acciones disponibles.Puede dar también a un método un nombre de la acción específica.De forma predeterminada, el nombre de un método también es su nombre de acción, pero si coloca [ActionName("help")] en su HomeController es acerca de método, entonces "acerca de" es ya no una acción válida para el controlador.En su lugar, nombre de la acción de acerca del método es "ayuda" y se invocar el método acerca de para las solicitudes de como o principal o ayuda y el marco de trabajo.

Un atributo de selector especialmente importante es el atributo AcceptVerbs.Este atributo sólo permite el marco seleccionar una acción cuando uno de los verbos aparecen en el atributo coincide con el verbo de la solicitud HTTP actual.Por ejemplo, decoración un with[AcceptVerbs(HttpVerbs.Post) método] significa que sólo se puede invocar el método como una acción para una operación HTTP POST.Es importante seleccionar el verbo adecuado para las acciones de controlador, especialmente si las acciones de modificar el estado en el servidor.Para obtener más información, consulteSugerencia de MVC ASP.NET Stephen Walther #46.

Filtrar atributos

Los filtros de acción son otro tipo de atributo que se puede colocar en una acción.Con los filtros de acción puede agregar el almacenamiento en caché, validación y los comportamientos de sus operaciones mediante un modelo de programación declarativa de tratamiento de errores.Un ejemplo de un atributo de filtro es el atributo [HandleError] en el HomeController en la figura 7 .Puede aplicar este atributo a acciones individuales, o agregar el atributo a la clase de controlador para aplicar el comportamiento a todas las acciones en un controlador.

Cuando un atributo HandleError está presente en una acción y la acción produce una excepción, el marco MVC buscará una vista con el nombre de "error", primero en vista carpeta el controlador y también en la carpeta de la vista compartida.La vista de errores permite presentar al usuario una página de error descriptivo.También puede asignar las excepciones a vistas específicas mediante un atributo HandleError más explícito.Por ejemplo, [HandleError(ExceptionType=typeof(SqlException), ver = "DatabaseError")] asignaría una SqlException no controlada a una vista denominada DatabaseError. El resto de los filtros de acción proporcionada por el marco MVC se resumen en la figura 8 .

Figura 8 filtros de acción
Nombre Descripción
OutputCacheAttribute Es similar a la directiva OutputCache de formularios Web de ASP.NET.El atributo OutputCache permite el marco MVC para almacenar en caché el resultado de un controlador.
ValidateInputAttribute Al igual que el atributo ValidateRequest en un formulario Web.De forma predeterminada, el marco MVC inspeccionará una solicitud HTTP entrante para HTML o otra entrada peligroso.Si detecta, se generará una excepción.Puede utilizar este atributo para deshabilitar la validación de solicitudes.
AuthorizeAttribute El atributo de autorizar permite colocar comprobaciones de autorización declarativa en controlador de acciones.El atributo puede restringir una acción a los usuarios de funciones específicas.Puede utilizar este atributo cuando se crea una acción que sólo deben disponibles para los usuarios en función de un administrador.
ValidateAntiForgeryTokenAttribute Este atributo es una mitad de la solución para ayudar a evitar que entre sitios solicitar forgeries (CSRF).Permite el marco de comprobar la presencia de un token específica del usuario en entradas de HTTP.Para obtener más información sobre CSRFs, consulte"Evitar que entre sitios solicitar falsificación (CSFR) con AntiForgeryToken() auxiliar ASP.NET MVC."

Filtros de acción personalizada

Puede crear sus propios filtros acción para rodear una acción con lógica personalizada.El código en la figura 9 es el código para un filtro de acción de registro simple que puede escribir en la salida de Windows de Visual Studio durante la depuración.Se puede aplicar este atributo a una acción individual, o se puede colocar este atributo en una clase de controlador que tiene el registro de todas las acciones en un controlador.

Figura 9 una acción de registro de filtro

public class LogAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Log("Action Executing", filterContext.RouteData);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        Log("Action Executed", filterContext.RouteData);
    }

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        Log("Result Executing", filterContext.RouteData);
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        Log("Result Executed", filterContext.RouteData);            
    }

    void Log(string stageName, RouteData routeData)
    {
        Debug.WriteLine(
            String.Format("{0}::{1} - {2}", 
                routeData.Values["controller"],
                routeData.Values["action"],
                stageName));
    }        
}

Como puede ver, hay cuatro métodos virtuales proporcionados por la clase ActionFilter base.Puede reemplazar uno o varios de estos métodos para no sólo las acciones de controlador de posprocesamiento y transmisión, pero también transmisión y proceso posterior según el resultado de la acción de controlador.Antes de se ejecuta una acción, se activará el método OnActionExecuting y cuando se haya completado la acción el OnActionExecuted método desencadenará (y se desencadenará incluso si la acción produce una excepción no controlada).Del mismo modo, el método OnResultExecuting desencadenará antes de que se ejecuta el resultado y el método OnResultExecuted desencadenará una vez.

El parámetro de contexto que se pasa a los métodos de filtro de acción le permitirá inspeccionar la solicitud HTTP, el contexto HTTP, los datos de ruta y más.Produce una excepción de uno de estos métodos se detendrá la flujo de procesamiento de solicitudes.Una excepción es una herramienta muy útil si está escribiendo un ActionFilter para Comprobar condiciones previas en el entorno.

Obtención de resultados

La ejecución correcta de una acción de controlador MVC dará como resultado un objeto derivado de ActionResult.Representar una vista y redirige el explorador a una nueva dirección URL son tipos válidos de los resultados que es posible que desee desde el controlador.La lista completa de tipos ActionResult derivado se muestra en la figura 10 .

Figura 10 ActionResult derivada tipos
Nombre Comportamiento del marco de trabajo Producir (método)
ContentResult Escribe un valor de cadena directamente en la respuesta HTTP. Contenido
EmptyResult No se escribe en la respuesta HTTP.  
FileContentResult Toma el contenido de un archivo (representado como una matriz de bytes) y escribir el contenido en la respuesta HTTP. Archivo
FilePathResult Toma el contenido de un archivo en la ubicación dada y escribe el contenido en la respuesta HTTP. Archivo
FileStreamResult Toma una secuencia de archivo generada por el controlador y escribe la secuencia en la respuesta HTTP. Archivo
HttpUnauthorizedResult Un resultado especial utilizado por los filtros de autorización cuando autorización comprueba errores.  
JavaScriptResult Responde al cliente con una secuencia de comandos para el cliente que se va a ejecutar. JavaScript
JsonResult Responde al cliente con los datos en JavaScript Object Notation (JSON). JSON
RedirectResult Redirige el cliente a una nueva dirección URL. Redirigir
RedirectToRouteResult Representa la vista especificada para responder con un fragmento HTML (normalmente, se utiliza en escenarios de AJAX). RedirectToRoute y RedirectToAction
PartialViewResult Representa la vista especificada para responder con un fragmento HTML (normalmente, se utiliza en escenarios de AJAX). PartialView
ViewResult Representa la vista especificada y responde al cliente con código HTML. Vista

Tenga en cuenta que una acción de controlador nunca tiene que crear una instancia de uno de estos tipos directamente.En su lugar, la acción de controlador puede invocar el nombre del método que se muestra en la figura 10 para generar el resultado.Estos métodos se heredan clase base del controlador de MVC.También es importante recordar que una acción de controlador no necesita devolver un objeto ActionResult.Si el controlador devuelve algo que no sea un ActionResult, el marco de trabajo se convertir el objeto en una cadena y ajustar la cadena en un ContentResult (que simplemente escribe la cadena en la respuesta HTTP).Un controlador que devuelve void dará como resultado un EmptyResult.

La clase ActionResult define un método ExecuteResult que cada uno de los tipos en la figura 10 reemplazará.Este método se invoca por la ControllerActionInvoker, el mismo objeto que llamó acción el controlador.Cuando se invoca, cada resultado se ocupará de todos los detalles de poco necesarios para entregar correctamente el resultado en el cliente.Por ejemplo, el resultado de JavaScript establecer el encabezado de tipo de contenido de la respuesta "Application/x-JavaScript", mientras el HttpUnauthorizedResult establecerá el código de estado HTTP de la respuesta a un 401 (no autorizado).

Una respuesta común de una acción de controlador será un ViewResult.Ha visto este resultado en listas de código anterior, tal como todas las acciones han llamó el método de vista del controlador y devuelve el resultado.Este es otro ejemplo de "convención sobre configuración," porque la ViewResult, cuando se utiliza en esta manera predeterminada, buscará una vista en la carpeta de vista el controlador y con un nombre de archivo que coincida con la acción.Por ejemplo, views\home\about.aspx es la vista convencional para la acción acerca del controlador principal de.Las versiones sobrecargadas del método vista permiten establezca explícitamente el nombre de la vista.

La acción es a través de

Este mes ha tomado un vistazo profundidad a la abstracciones y comportamiento que lo rodea los controladores de ASP.NET MVC.Yo u ahora debe tener una buena explicación de cómo se busca el marco MVC, crea y utiliza los controladores, así como enlazar a los puntos de extensibilidad del marco MVC que giran en torno a los controladores.En la próxima edición de esta columna, le eche un vistazo a directrices y recomendaciones para colocar estos controladores para trabajar en aplicaciones reales.

Perspectivas: los métodos auxiliares

Si pensó extraño utiliza los métodos auxiliares para resultados de acción cuando aparecían en primer lugar en el marco de trabajo (View(), Content()), quizá se pregunte cómo todo surgió y lo que era detrás de esa decisión de diseño en concreto.

Bien, el artículo detrás de los métodos auxiliares para devolver los resultados de la acción es que va 99% de tiempo que un desarrollador MVC escribiendo una aplicación de MVC para gastarse escribir el controlador de acciones.Deseaba asegurarse de que el método típico es desde el principio, puede leer y como declarativo como sea posible.

Por ejemplo, todavía puede escribir un método de acción así:

  public ActionResult Foo {
// ... do stuff ...
ViewData.Model = myModel;
return new ViewResult {ViewName = "Foo", ViewData = this.ViewData};
}

 
Deseábamos limpiar Esto un poco, para que hemos realizado algunos ajustes, como puede ver:

  public ActionResult Foo {
// ... do stuff ...
return new View(myModel);
}

 
Esto es un enfoque más declarativo (aunque el uso de un lenguaje muy imprescindible).Al leer ese método de acción, refleja su intención. "Desea devolver una vista que contiene este modelo."

--Phil Haak, director de programas, Microsoft