【问题标题】:ASP.NET MVC: Is Controller created for every request?ASP.NET MVC:是否为每个请求创建了控制器?
【发布时间】:2011-07-22 12:10:00
【问题描述】:

非常简单的问题:ASP.NET 中的控制器是为每个 HTTP 请求创建的,还是在应用程序启动时创建并在整个请求中重复使用?

是否仅为特定的 HTTP 请求创建控制器?

如果我之前的假设是正确的,我可以依赖它吗?我想创建仅适用于一个请求的数据库上下文(实体框架)。如果我将它创建为在控制器的构造函数中初始化的属性,是否允许为每个请求创建新的上下文实例?

【问题讨论】:

  • 在你的构造函数中放一个断点,看看你能找到什么......
  • @Greg B:好主意,除了它不会告诉我它是否总是这样 - 如果情况发生变化并且某些控制器会改变它的行为,我有可能很难找到的错误......
  • @Todd Smith 请提供一些链接或至少是全名。树字母 IoC 很难用谷歌搜索。谢谢。
  • @drasto IoC = 控制反转en.wikipedia.org/wiki/Inversion_of_control

标签: .net asp.net-mvc-3 entity-framework controller httprequest


【解决方案1】:

ControllerFactory(默认为DefaultControllerFactory)为每个请求创建一个控制器。

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

注意Html.Action Html Helper 将创建另一个控制器。

简短的版本是(对于每个请求)调用ControllerActivator.Create 来创建一个控制器(它通过 DependencyResolver 或如果没有设置解析器则通过激活器初始化一个新的控制器):

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

这可能包含太多信息...但我想表明您确实为每个请求都获得了一个新控制器。

【讨论】:

【解决方案2】:

我为控制器创建了一个空的构造函数,并在构造函数中放置了一个断点。每次有新请求时都会受到打击。所以我认为它是为每个请求创建的。

【讨论】:

  • +1 我希望你是对的,但我想要一些更好的认可知识,而不仅仅是“在我尝试过的所有情况下都有效”。如果它有时由于某种原因不能那样工作,那就意味着一个错误。
  • @drasto:不用担心。控制器为每个请求实例化。虽然有些内存确实会被重用,但你不应该担心控制器状态(如果你有的话)。它将按预期初始化。 但是可能会出现多个控制器被实例化的情况。这就是视图调用控制器操作的时候(即Html.RenderAction("action", "controller");
【解决方案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

    【讨论】:

    • 需要引用 - 在链接文档中找不到支持信息。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 2014-01-23
    • 2012-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多