ASP.NET MVC: Чи створюється контролер для кожного запиту?


112

Дуже просте запитання: чи створені контролери в ASP.NET для кожного запиту HTTP, чи вони створюються при запуску програми та повторно використовуються протягом запитів?

Чи буде створений контролер лише для конкретного запиту HTTP?

Якщо мої попередні припущення є правильними, чи можу я залежати від цього? Я хочу створити контекст бази даних (Entity Framework), який працюватиме лише для одного запиту. Якщо я створюю її як властивість, ініціалізовану в конструкторі контролера, чи буде надано новий екземпляр контексту для кожного запиту?


16
Поставте точку перелому у своєму конструкторі та подивіться, що ви можете дізнатися ...
Грег Б

10
@Greg B: відмінна ідея , за винятком того, що не говоритиме мені , якщо він веде себе так, як це завжди - якщо обставини зміни і деякі контролер змінить свою поведінку , у мене є помилка , яка може бути дуже важко знайти ...
Rasto

@drasto як ти перевіриш, чи працює так завжди? Перевірити кожен запит на вашу заявку?
Грег Б

4
@Todd Smith будь ласка, будь-яке посилання або хоча б повне ім’я. Дерево букви IoC важко гугл. Дякую.
Расто

2
@drasto IoC = Інверсія управління en.wikipedia.org/wiki/Inversion_of_control
Бала R

Відповіді:


103

Для кожного запиту створюється контролер ControllerFactory(який за замовчуванням є DefaultControllerFactory).

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

Зауважте, що Html.ActionHtml Helper створить інший контролер.

Коротка версія полягає в тому, що ControllerActivator.Createвикликається (для кожного запиту) для створення контролера (який вводить новий контролер або через DependencyResolver, або через активатор, якщо Resolver не встановлений):

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

Більш довга версія це (ось код з джерела від 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));
    }
}

Ось заводський код контролера:

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

Що в основному називає це:

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

Хто викликає цей метод у ControllerActivator(Цей код намагається запитати DependencyResolver для екземпляра або просто використовує клас Activator):

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

Це може потрапити під занадто багато інформації ... Але я хотів показати, що ви дійсно отримуєте новий контролер для кожного запиту.


@Daniel @drasto ось цитування aspnet.codeplex.com/SourceControl/changeset/view/63930#266503
Bala R

32

Я створив порожній конструктор для контролера і поставив точку розриву в конструкторі. Він потрапляв щоразу, коли з’являвся новий запит. Тому я думаю, що він створений для кожного запиту.


3
+1 Я сподіваюся, що ти маєш рацію, але я хотів би трохи краще затверджених знань, ніж просто "у всіх випадках, коли я це намагався". Якщо іноді це не працює так, то з якихось причин це означає помилку.
Расто

6
@drasto: Не потрібно хвилюватися. Контролер отримує екземпляр для кожного запиту. Деякі пам’яті все-таки повторно використовуються, але вам не варто турбуватися про стан контролера (якщо у вас є такий). Він буде ініціалізований, як очікувалося. Але може виникнути ситуація, коли більше одного контролера отримає екземпляр. І ось тоді погляди викликають дії контролера (тобто Html.RenderAction("action", "controller");)
Роберт Коритник

@RobertKoritnik & Bala R, у мене питання, будь ласка. Що відбувається з об’єктами, створеними на зразок Student або List <Student> після того, як метод дії подав його або їх перегляду? Чи їх утилізують? А що відбувається з цими об’єктами, коли надходить новий запит?
Махді Алхатіб

3

Контролер буде створений, коли виконується будь-яка дія в певному контролері.

У мене є проект, де всі мої контролери успадковують від ApplicationControllerкожного разу, коли виконується дія, точка зламу потрапляє всередину ApplicationController- незалежно від " поточного " контролера.

Я ініціалізую свого агента (який працює як мій контекст) кожного разу, коли мій контролер створений таким:

    public IWidgetAgent widgetAgent { get; set; }

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

    }

Це, очевидно, не те, що вам потрібно - як ви згадали, що хотіли лише один екземпляр кожного разу, коли він викликався. Але це хороше місце, щоб перевірити, що відбувається щоразу, і переконатися, що інший екземпляр вашого контексту не існує на даний момент.

Сподіваюся, це допомагає.


2

Контролери створюються для кожного запиту. Чара відбувається в маршрутизації в gobal.aspx. Шляхи відображення спрямовують MVC, до якого контролеру створювати та діяти на контролері для виклику, та параметри, що передаються їм.

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


необхідне цитування - не може знайти допоміжну інформацію у пов'язаному документі. Дякую
Расто,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.