ASP MVC: ¿Cuándo se llama IController Dispose ()?

Estoy pasando por un gran cambio de refactorización / velocidad de una de mis aplicaciones MVC más grandes. Se ha implementado en la producción durante unos meses y estaba empezando a tener tiempos de espera esperando conexiones en el grupo de conexiones. He rastreado el problema hasta que las conexiones no se eliminan adecuadamente.

A la luz de eso, desde entonces he hecho este cambio en mi controlador base:

public class MyBaseController : Controller { private ConfigurationManager configManager; // Manages the data context. public MyBaseController() { configManager = new ConfigurationManager(); } protected override void Dispose(bool disposing) { if (disposing) { if (this.configManager != null) { this.configManager.Dispose(); this.configManager = null; } } base.Dispose(disposing); } } 

Ahora, tengo dos preguntas:

  1. ¿Estoy presentando una condición de carrera? Dado que configManager administra el DataContext que expone los parámetros IQueryable a las vistas, necesito asegurarme de que Dispose() no se invoque en el controlador antes de que la vista termine de renderizarse.
  2. ¿La estructura de MVC llama a Dispose() en el controlador antes o después de que se visualice la vista? O, ¿el marco de MVC lo deja hasta GarbageCollector?

Dispose se llama después de que la vista se represente, siempre .

La vista se representa en la llamada a ActionResult.ExecuteResult . Eso se llama (indirectamente) por ControllerActionInvoker.InvokeAction , que a su vez es llamado por ControllerBase.ExecuteCore .

Dado que el controlador está en la stack de llamadas cuando se representa la vista, entonces no se puede eliminar.

Solo para ampliar la respuesta de Craig Stuntz :

ControllerFactory maneja cuando un controlador está dispuesto. Al implementar la interfaz IControllerFactory, uno de los métodos que necesita implementarse es ReleaseController.

No estoy seguro de qué ControllerFactory está utilizando, ya sea que lo haya hecho, pero en Reflector mirando DefaultControllerFactory, el método ReleaseController se implementa de la siguiente manera:

 public virtual void ReleaseController(IController controller) { IDisposable disposable = controller as IDisposable; if (disposable != null) { disposable.Dispose(); } } 

Se transfiere una referencia de IController, si ese controlador implementa IDisposable, entonces se llama al método Dispose de los controladores. Por lo tanto, si tiene algo que necesita eliminar después de que la solicitud finalice, que es después de que se visualice la vista. Heredar de IDisposable y poner su lógica en el método Dispose para liberar cualquier recurso.

El método System.Web.Mvc.MvcHandler llama al método ReleaseController, que maneja la solicitud e implementa IHttpHandler. El ProcessRequest toma el HttpContext dado a él y comienza el proceso de encontrar el controlador para manejar la solicitud, llamando al ControllerFactory implementado. Si observa el método ProcessRequest, verá el bloque finally que llama al ReleaseController de ControllerFactory. Esto solo se llama cuando el Controlador ha devuelto ViewResult.