ASP.NET MVC: Denetleyici her istek için oluşturulmuş mu?


112

Çok basit bir soru: ASP.NET'teki denetleyiciler her HTTP isteği için mi oluşturuluyor yoksa uygulama başlangıcında mı oluşturuluyor ve istekler boyunca yeniden kullanılıyor mu?

Denetleyici yalnızca belirli bir HTTP isteği için mi oluşturulacak?

Önceki varsayımlarım doğruysa, buna güvenebilir miyim? Yalnızca bir istek için yaşayacak veritabanı bağlamı (Entity Framework) oluşturmak istiyorum. Bunu denetleyicinin kurucusunda başlatılan bir özellik olarak oluşturursam, her istek için yeni bağlam örneğinin oluşturulacağı verilir mi?


16
Yapıcınıza bir kesme noktası koyun ve ne bulabileceğinizi görün ...
Greg B

10
@Greg B: Harika bir fikir, her zaman böyle davranıp davranmadığını bana söylememesi dışında - koşullar değişirse ve bazı kontrolörler davranışını değiştirirse, bulması gerçekten zor olabilecek bir
hatam var

@drasto her zaman böyle çalışıp çalışmadığını nasıl kontrol edeceksiniz? Başvurunuz için her talebi kontrol edin?
Greg B

4
@Todd Smith lütfen bir bağlantı veya en azından tam ad. Ağaç harfleri IoC'yi google'da aramak zordur. Teşekkür ederim.
Rasto

2
@drasto IoC = Kontrolün tersine çevrilmesi en.wikipedia.org/wiki/Inversion_of_control
Bala R

Yanıtlar:


103

Her istek için bir Denetleyici oluşturulur ControllerFactory(varsayılan olarak budur DefaultControllerFactory).

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

Html.ActionHtml Helper'ın başka bir denetleyici oluşturacağını unutmayın .

Kısa versiyon, ControllerActivator.Create(her istek için) bir Denetleyici (DependencyResolver veya Çözücü kurulmamışsa Aktivatör aracılığıyla yeni bir Denetleyici başlatan) oluşturmak için çağrılır:

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

Daha uzun sürüm şudur (İşte MvcHandler'daki kaynaktan gelen kod):

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));
    }
}

Denetleyicinin fabrika kodu:

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

Temelde buna şöyle der:

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

Bu yöntemi içinde ControllerActivator(Bu kod DependencyResolver'dan bir örnek istemeye çalışır veya yalnızca Activator sınıfını kullanır):

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

Bu çok fazla bilgi kapsamına girebilir ... Ancak HER istek için gerçekten yeni bir kontrol cihazı aldığınızı göstermek istedim.



32

Bir denetleyici için boş bir kurucu yarattım ve kurucuya bir kırılma noktası koydum. Her yeni talep geldiğinde vuruldu. Bu yüzden her istek için yaratıldığını düşünüyorum.


3
+1 Umarım haklısınızdır, ancak "denediğim her durumda" işe yaradığından daha iyi onaylanmış bir bilgi istiyorum. Bazen böyle çalışmıyorsa bir nedenden dolayı bir hata anlamına gelir.
Rasto

6
@drasto: Endişelenmenize gerek yok. Denetleyici her istek için somutlaştırılır. Yine de bazı bellekler yeniden kullanılır, ancak denetleyici durumu hakkında endişelenmemelisiniz (sizinki varsa). Beklendiği gibi başlatılacaktır. Ancak birden fazla denetleyicinin somutlaştırılacağı bir durum olabilir. Ve bu, görünümler denetleyici eylemlerini çağırdığında (ör. Html.RenderAction("action", "controller");)
Robert Koritnik

@RobertKoritnik & Bala R, bir sorum var lütfen. Eylem yöntemi onu veya onlara görünüme sunduktan sonra Student veya List <Student> gibi oluşturulan nesneler için ne olur? Elden çıkarılıyorlar mı? Yeni bir talep geldiğinde bu nesneler için ne olur?
Mahdi Alkhatib

3

Denetleyici, belirli bir Denetleyicide herhangi bir Eylem gerçekleştirildiğinde oluşturulacaktır.

Tüm Denetleyicilerimin ApplicationControllerbir işlemden miras aldığı bir projem var ve bir eylem her gerçekleştirildiğinde, ApplicationController" mevcut " Denetleyiciden bağımsız olarak kesme noktası içinde vuruluyor .

Denetleyicim şu şekilde oluşturulduğunda (bağlamım olarak çalışan) aracımı başlatırım:

    public IWidgetAgent widgetAgent { get; set; }

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

    }

Açıkçası ihtiyacınız olan şey bu değil - bahsettiğiniz gibi, her çağrıldığında yalnızca tek bir örnek istediğinizi belirtmişsiniz. Ancak her seferinde neler olup bittiğini kontrol etmek ve bağlamınızın başka bir örneğinin şu anda mevcut olmadığından emin olmak için iyi bir yerdir.

Bu yardımcı olur umarım.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.