ASP MVC: quando viene chiamato IController Dispose ()?

Sto passando attraverso un grande refactoring / velocizzazione di una delle mie applicazioni MVC più grandi. È stato distribuito in produzione per alcuni mesi e stavo iniziando a ottenere timeout in attesa di connessioni nel pool di connessioni. Ho rintracciato il problema fino a quando le connessioni non vengono smaltite correttamente.

Alla luce di ciò, ho apportato questa modifica al mio controller di 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); } } 

Ora ho due domande:

  1. Sto introducendo una condizione di gara? Poiché configManager gestisce il DataContext che espone i parametri IQueryable alle viste, devo assicurarmi che Dispose() non venga chiamato sul controller prima che la visualizzazione finisca il rendering.
  2. Il framework MVC chiama Dispose() sul controller prima o dopo il rendering della vista? Oppure, il framework MVC lo lascia fino a GarbageCollector?

Dispose viene chiamato dopo il rendering della vista, sempre .

La vista viene visualizzata nella chiamata a ActionResult.ExecuteResult . Questo viene chiamato (indirettamente) da ControllerActionInvoker.InvokeAction , che a sua volta viene chiamato da ControllerBase.ExecuteCore .

Poiché il controller si trova nello stack di chiamate quando viene eseguito il rendering della vista, non può essere eliminato.

Solo per espandere la risposta di Craig Stuntz :

ControllerFactory gestisce quando viene smaltito un controller. Quando si implementa l’interfaccia IControllerFactory, uno dei metodi che deve essere implementato è ReleaseController.

Non sono sicuro di quale ControllerFactory si sta utilizzando, indipendentemente dal fatto che si sia fatto da soli, ma in Reflector guardando DefaultControllerFactory, il metodo ReleaseController è implementato in questo modo:

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

Viene passato un riferimento IController, se quel controller implementa IDisposable, allora viene chiamato quel metodo Dispose di controller. Quindi, se hai qualcosa da smaltire dopo il completamento della richiesta, che è dopo che la vista è stata renderizzata. Eredita da IDisposable e inserisci la tua logica nel metodo Dispose per rilasciare qualsiasi risorsa.

Il metodo ReleaseController viene chiamato da System.Web.Mvc.MvcHandler che gestisce la richiesta e implementa IHttpHandler. Il ProcessRequest prende il HttpContext dato ad esso e avvia il processo di trovare il controller per gestire la richiesta, chiamando il ControllerFactory implementato. Se si guarda nel metodo ProcessRequest, verrà visualizzato il blocco finally che chiama ReleaseController di ControllerFactory. Questo viene chiamato solo quando il Controller ha restituito un ViewResult.