ASP.NET MVC: создан ли контроллер для каждого запроса?

Очень простой вопрос: Созданы ли контроллеры в ASP.NET для каждого HTTP-запроса или созданы они при запуске приложения и повторно используются во всех запросах?

Будет ли контроллер создан только для конкретного HTTP-запроса?

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

Ответ 1

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

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

Обратите внимание, что Html.Action Html 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));
            }
        }

Здесь код контроллера factory

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

Это может подпадать под слишком много информации... Но я хотел показать, что вы действительно получите новый контроллер для КАЖДОГО запроса.

Ответ 2

Я создал пустой конструктор для контроллера и поместил точку останова в конструкторе. Он попадал каждый раз, когда появлялся новый запрос. Поэтому я думаю, что он создан для каждого запроса.

Ответ 3

Контроллер будет создан, когда будет выполнено любое действие в определенном контроллере.

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

Я инициализирую свой агент (который работает как мой контекст), когда мой контроллер создается следующим образом:

    public IWidgetAgent widgetAgent { get; set; }

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

    }

Это, очевидно, не то, что вам нужно, поскольку вы упомянули, что каждый раз, когда он был вызван, вам нужен только один экземпляр. Но это хорошее место для проверки того, что происходит каждый раз, и для обеспечения того, чтобы другой экземпляр вашего контекста в настоящее время не существует.

Надеюсь, что это поможет.

Ответ 4

Контроллеры создаются для каждого запроса. Магия происходит в маршрутизации в gobal.aspx. Пути сопоставления направляют MVC к контроллеру для создания и действия над контроллером для вызова и параметры для их передачи.

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