非常简单的问题:ASP.NET中的控制器是为每个HTTP请求创建的,还是在应用程序启动时创建并在整个请求中重用?
是否只为特定的HTTP请求创建控制器?
如果我以前的假设是正确的,我可以依赖吗?我想创建仅适用于一个请求的数据库上下文(实体框架)。如果我将它创建为在控制器的构造函数中初始化的属性,是否会为每个请求创建新的上下文实例?
答案 0 :(得分:88)
ControllerFactory为每个请求创建一个Controller(默认情况下是DefaultControllerFactory)。
http://msdn.microsoft.com/en-us/library/system.web.mvc.defaultcontrollerfactory.aspx
请注意,Html.Action
Html Helper将创建另一个控制器。
简短版本是ControllerActivator.Create
被调用(对于每个请求)来创建一个控制器(如果没有设置解析器,它将通过DependencyResolver或通过Activator进入新控制器):
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));
}
这可能属于太多信息......但我想表明你确实为每个请求获得了一个新的控制器。
答案 1 :(得分:28)
我为控制器创建了一个空构造函数,并在构造函数中放置了一个断点。每当有新请求时它就会被击中。所以我认为它是为每个请求创建的。
答案 2 :(得分:3)
当执行特定控制器中的任何操作时,将创建控制器。
我有一个项目,我的所有控制器都从ApplicationController
继承而且每次执行一个动作时,断点都会在ApplicationController
内部被触及 - 无论其“当前“控制器。
每当我的控制器被创建时,我初始化我的代理(它作为我的上下文):
public IWidgetAgent widgetAgent { get; set; }
public WidgetController()
{
if (widgetAgent == null)
{
widgetAgent = new WidgetAgent();
}
}
这显然不是您所需要的 - 正如您所提到的,每次调用时您只需要一个实例。但它是一个检查每次发生的事情并确保当前不存在上下文实例的好地方。
希望这有帮助。
答案 3 :(得分:2)
为每个请求创建控制器。魔术发生在gobal.aspx的路由中。映射路径指向MVC,控制器在控制器上创建和操作以及要传递给它们的参数。
http://www.asp.net/mvc/tutorials/asp-net-mvc-routing-overview-vb