2011-03-24 13 views
67

Pregunta muy simple: ¿Los controladores en ASP.NET se crean para cada solicitud HTTP, o se crean al inicio de la aplicación y se reutilizan en todas las solicitudes?ASP.NET MVC: ¿Se creó el controlador para cada solicitud?

¿Se creará el controlador solo para una solicitud HTTP en particular?

Si mis suposiciones anteriores son correctas, ¿puedo confiar en ello? Quiero crear un contexto de base de datos (Entity Framework) que viva solo para una solicitud. Si lo creo como una propiedad inicializada en el constructor del controlador, ¿se concede que se creará una nueva instancia de contexto para cada solicitud?

+11

Ponga un punto de interrupción en su constructor y vea lo que puede encontrar ... –

+3

@Greg B: gran idea, excepto que no me dirá si se comporta así siempre - si las circunstancias cambian y algún controlador cambiará su comportamiento I tiene un error que puede ser muy difícil de encontrar ... – drasto

+0

@drasto ¿cómo va a comprobar si funciona así siempre? Compruebe cada solicitud a su aplicación? –

Respuesta

73

Un controlador está creado para cada solicitud por el ControllerFactory (que por defecto es el DefaultControllerFactory).

http://msdn.microsoft.com/en-us/library/system.web.mvc.defaultcontrollerfactory.aspx

Tenga en cuenta que la Html.Action HTML ayudante creará otro controlador.

La versión corta es que ControllerActivator.Create se llama (para cada solicitud) para crear un controlador (que INITs un nuevo controlador, ya sea a través de la DependencyResolver oa través del Activador si no hay Resolver se ha establecido):

public IController Create(RequestContext requestContext, Type controllerType) { 
        try { 
         return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType)); 
        } 

la versión más larga es la siguiente (Aquí está el código de la fuente desde el MvcHandler)

protected internal virtual void ProcessRequest(HttpContextBase httpContext) 
    { 
     SecurityUtil.ProcessInApplicationTrust(() => 
     { 
      IController controller; 
      IControllerFactory factory; 
      ProcessRequestInit(httpContext, out controller, out factory); 

      try 
      { 
       controller.Execute(RequestContext); 
      } 
      finally 
      { 
       factory.ReleaseController(controller); 
      } 
     }); 
    } 

private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory) 
     { 
      //non relevant code 

      // Instantiate the controller and call Execute 
      factory = ControllerBuilder.GetControllerFactory(); 
      controller = factory.CreateController(RequestContext, controllerName); 
      if (controller == null) 
      { 
       throw new InvalidOperationException(
        String.Format(
         CultureInfo.CurrentCulture, 
         MvcResources.ControllerBuilder_FactoryReturnedNull, 
         factory.GetType(), 
         controllerName)); 
      } 
     } 

Aquí está el código de fábrica controlador

public virtual IController CreateController(RequestContext requestContext, string controllerName) { 
      Type controllerType = GetControllerType(requestContext, controllerName); 
      IController controller = GetControllerInstance(requestContext, controllerType); 
      return controller; 
     } 

que se pide básicamente esto:

protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType) { 
      return ControllerActivator.Create(requestContext, controllerType); 
     } 

que llama a este método en el ControllerActivator (Este código intenta pedir al DependencyResolver para una instancia, o simplemente utiliza la clase Activador):

public IController Create(RequestContext requestContext, Type controllerType) { 
       try { 
        return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType)); 
       } 

Esto podría caer en Demasiada información ... Pero quería mostrar que realmente OBTIENE un nuevo controlador para CADA petición.

+1

{{citation needed} } –

+0

Realmente se necesita. No puedo encontrar ninguna información de este tipo ... – drasto

+1

http://msdn.microsoft.com/en-us/library/dd381612.aspx – BlackICE

24

Creé un constructor vacío para un controlador y puse un punto de interrupción en el constructor. Recibió un golpe cada vez que hubo una nueva solicitud. Así que creo que está creado para cada solicitud.

+2

+1 Espero que tenga razón, pero me gustaría obtener un mejor conocimiento aprobado que solo "en todos los casos en que lo he intentado funcionó ". Si a veces no funciona así por alguna razón, significa un error. – drasto

+6

@drasto: No hay de qué preocuparse. El controlador se crea una instancia para cada solicitud. Sin embargo, algunos recuerdos se reutilizan, pero no debes preocuparte por el estado del controlador (si el tuyo tiene uno). Se inicializará como se espera. ** Pero ** puede haber una situación en la que se creará una instancia de más de un controlador. Y es entonces cuando las vistas llaman acciones del controlador (es decir, 'Html.RenderAction (" acción "," controlador ");') –

+0

@RobertKoritnik & Bala R, tengo una pregunta, por favor. ¿Qué sucede con los objetos creados como Student o List después de que el método de acción los haya servido a la vista? ¿Se eliminan? ¿Y qué ocurre con estos objetos cuando llega una nueva solicitud? –

2

El controlador se creará cuando se realice cualquier acción en un controlador específico.

Tengo un proyecto en el que todos mis controladores heredan de una ApplicationController y cada vez que se realiza una acción, el punto de interrupción se golpeó en el interior de la ApplicationController - independientemente de su "actual " Controlador.

Me inicializar mi agente (que funciona como mi contexto) cada vez que se crea mi regulador, como por ejemplo:

public IWidgetAgent widgetAgent { get; set; } 

    public WidgetController() 
    { 
     if (widgetAgent == null) 
     { 
      widgetAgent = new WidgetAgent(); 
     } 

    } 

Esto obviamente no es lo que necesita - como usted ha mencionado que sólo quería una sola instancia cada vez fue llamado. Pero es un buen lugar para verificar lo que está sucediendo cada vez y para asegurarse de que no exista otra instancia de su contexto actualmente.

Espero que esto ayude.

1

Los controladores se crean para cada solicitud. La magia ocurre en el enrutamiento en gobal.aspx. Las rutas de mapeo dirigen MVC a qué controlador crear y actuar en el controlador para llamar, y los parámetros que se les pasan.

http://www.asp.net/mvc/tutorials/asp-net-mvc-routing-overview-vb

+0

* cita requerida *: no se puede encontrar información de respaldo en un documento vinculado. Gracias – drasto

+1

http://stackoverflow.com/questions/1763775/asp-net-mvc-controller-lifecycle – BlackICE

+1

http://msdn.microsoft.com/en-us/library/dd381612.aspx – BlackICE

Cuestiones relacionadas