Search code examples
.netasp.net-mvc-3entity-frameworkcontrollerhttprequest

ASP.NET MVC: Is Controller created for every request?


Very simple question: Are controllers in ASP.NET created for every HTTP request, or are they created at application startup and reused throughout requests?

Will the controller be created only for a particular HTTP request?

If my previous assumptions are correct, can I depend on it? I want to create database context (Entity Framework) that will live only for one request. If I create it as a property initialized in controller's constructor, is it granted that new instance of context will be created on for every request?


Solution

  • A Controller is created for every request by the ControllerFactory (which by default is the DefaultControllerFactory).

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

    Note that the Html.Action Html Helper will create another controller.

    The short version is that ControllerActivator.Create is called (for every request) to create a Controller (which inits a new Controller either through the DependencyResolver or through the Activator if no Resolver has been set up):

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

    The longer version is this (Here's the code from the source from the 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));
        }
    }
    

    Here's the Controller factory code:

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

    Which basically calls this:

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

    Which calls this method in the ControllerActivator (This code tries to ask the DependencyResolver for an instance, or just uses the Activator class):

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

    This might fall under too much information... But I wanted to show that you really DO get a new controller for EVERY request.