ASP.NET MVC: Контроллер создается для каждого запроса? - PullRequest
92 голосов
/ 25 марта 2011

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

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

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

Ответы [ 4 ]

89 голосов
/ 25 марта 2011

Контроллер создается для каждого запроса 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));
            }
        }

Вот код фабрики контроллера

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

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

28 голосов
/ 25 марта 2011

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

3 голосов
/ 25 марта 2011

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

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

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

    public IWidgetAgent widgetAgent { get; set; }

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

    }

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

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

2 голосов
/ 25 марта 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...