一、Asp.Net MVC是否针对每次请求都重新创建一个控制器实例
默认情况下,答案是确定的。
ControllerBuilder类 ControllerBuilder.Current用户获取默认的控制器工厂DefaultControllerFactory
//
// 摘要:
// 表示默认情况下已注册的控制器工厂。
public class DefaultControllerFactory : IControllerFactory
获取方式
IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
IControllerFactory用户创建和释放Controller
namespace System.Web.Mvc
{
//
// 摘要:
// 定义控制器工厂所需的方法。
public interface IControllerFactory
{
//
// 摘要:
// 使用指定的请求上下文来创建指定的控制器。
//
// 参数:
// requestContext:
// 请求上下文。
//
// controllerName:
// 控制器的名称。
//
// 返回结果:
// 控制器。
IController CreateController(RequestContext requestContext, string controllerName);
//
// 摘要:
// 获取控制器的会话行为。
//
// 参数:
// requestContext:
// 请求上下文。
//
// controllerName:
// 你想要获取器其会话行为的控制器的名称。
//
// 返回结果:
// 控制器的会话行为。
SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName);
//
// 摘要:
// 释放指定的控制器。
//
// 参数:
// controller:
// 控制器。
void ReleaseController(IController controller);
}
}
二、答案验证方式一,查看源代码
目前Asp.Net MVC最先版本v5.2.4 ,CodeFlex源代码地址:http://aspnetwebstack.codeplex.com/SourceControl/latest
CodeFlex源代码Asp.Net首页:http://aspnetwebstack.codeplex.com/
官方MVC文档参考:https://www.asp.net/mvc
.Net Function 博客:https://dotnetfoundation.org/projects?q=mvc
关于Controller的实例化:
默认情况下,MVC的控制器工厂使用DefaultControllerFactory,继承了IControllerFactory,所以在默认控制器工厂中实现的CreateController()方法,就是用来创建控制器实例。
特别说明:从默认控制器工厂的Create()源代码看,每次请求都会创建对应的控制器实例,并且是通过反射的方式创建的。
源代码片段:来自DefaultControllerFactory
public virtual IController CreateController(RequestContext requestContext, string controllerName)
{
if (requestContext == null)
{
throw new ArgumentNullException("requestContext");
} if (String.IsNullOrEmpty(controllerName) && !requestContext.RouteData.HasDirectRouteMatch())
{
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName");
} Type controllerType = GetControllerType(requestContext, controllerName);
IController controller = GetControllerInstance(requestContext, controllerType);
return controller;
}
本类中的Create()方法
public IController Create(RequestContext requestContext, Type controllerType)
{
try
{
return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType));
}
catch (Exception ex)
{
throw new InvalidOperationException(
String.Format(
CultureInfo.CurrentCulture,
MvcResources.DefaultControllerFactory_ErrorCreatingController,
controllerType),
ex);
}
}
关于Controller的继承关系:
特别说明:在System.Web.Mvc.Dll中
1.IController中的Execute() 方法是在ControllerBase中实现的,Execute()中执行的操作主要操作:
1.实例化Controller实例,调用Initialize(),从这个方法中可以看出每次都是重新实例化控制器上线文ControllerContext对象
2.调用子类的ExecuteCore(),也就是Controller类中定义的ExecuteCore()
源代码片段,来自ControllerBase类:
protected virtual void Execute(RequestContext requestContext)
{
if (requestContext == null)
{
throw new ArgumentNullException("requestContext");
}
if (requestContext.HttpContext == null)
{
throw new ArgumentException(MvcResources.ControllerBase_CannotExecuteWithNullHttpContext, "requestContext");
} VerifyExecuteCalledOnce();
Initialize(requestContext);//初始化ControllerBase对象
using (ScopeStorage.CreateTransientScope())
{
ExecuteCore();
}
}
protected virtual void Initialize(RequestContext requestContext)
{
ControllerContext = new ControllerContext(requestContext, this);
}
2.Controller中只有ExecuteCore() 方法用于
1.激活Action方法并执行
2.处理View视图加载,视图代码编译执行,并呈现
Controller中的代码片段:
protected override void ExecuteCore()
{
// If code in this method needs to be updated, please also check the BeginExecuteCore() and
// EndExecuteCore() methods of AsyncController to see if that code also must be updated. PossiblyLoadTempData();
try
{
string actionName = GetActionName(RouteData);
if (!ActionInvoker.InvokeAction(ControllerContext, actionName))
{
HandleUnknownAction(actionName);
}
}
finally
{
PossiblySaveTempData();
}
}
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
} Contract.Assert(controllerContext.RouteData != null);
if (String.IsNullOrEmpty(actionName) && !controllerContext.RouteData.HasDirectRouteMatch())
{
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
} ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName); if (actionDescriptor != null)
{
FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor); try
{
AuthenticationContext authenticationContext = InvokeAuthenticationFilters(controllerContext, filterInfo.AuthenticationFilters, actionDescriptor); if (authenticationContext.Result != null)
{
// An authentication filter signaled that we should short-circuit the request. Let all
// authentication filters contribute to an action result (to combine authentication
// challenges). Then, run this action result.
AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(
controllerContext, filterInfo.AuthenticationFilters, actionDescriptor,
authenticationContext.Result);
InvokeActionResult(controllerContext, challengeContext.Result ?? authenticationContext.Result);
}
else
{
AuthorizationContext authorizationContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
if (authorizationContext.Result != null)
{
// An authorization filter signaled that we should short-circuit the request. Let all
// authentication filters contribute to an action result (to combine authentication
// challenges). Then, run this action result.
AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(
controllerContext, filterInfo.AuthenticationFilters, actionDescriptor,
authorizationContext.Result);
InvokeActionResult(controllerContext, challengeContext.Result ?? authorizationContext.Result);
}
else
{
if (controllerContext.Controller.ValidateRequest)
{
ValidateRequest(controllerContext);
} IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters); // The action succeeded. Let all authentication filters contribute to an action result (to
// combine authentication challenges; some authentication filters need to do negotiation
// even on a successful result). Then, run this action result.
AuthenticationChallengeContext challengeContext = InvokeAuthenticationFiltersChallenge(
controllerContext, filterInfo.AuthenticationFilters, actionDescriptor,
postActionContext.Result);
InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters,
challengeContext.Result ?? postActionContext.Result);
}
}
}
catch (ThreadAbortException)
{
// This type of exception occurs as a result of Response.Redirect(), but we special-case so that
// the filters don't see this as an error.
throw;
}
catch (Exception ex)
{
// something blew up, so execute the exception filters
ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
if (!exceptionContext.ExceptionHandled)
{
throw;
}
InvokeActionResult(controllerContext, exceptionContext.Result);
} return true;
} // notify controller that no method matched
return false;
}
三、答案验证方式二、通过控制器的构造函数验证
1.在控制器方法中,设置断电,启动调试
2.通过访问同一个控制器,相同或不同的Action,发现每次断电都会停住。
public class HomeController : Controller
{
/// <summary>
/// 构造函数
/// </summary>
public HomeController()
{
/*
* 特别说明:
* 1.MVC请求机制,中会为每一次请求都重新创建一个控制器实例,也就是说针对每一次请求该构造函数都会执行
* 2.在控制器的构造函数中,当前控制器的 http上线文(HttpContextBase)、当前请求上下文(HttpRequestBase)、路由当前路由数据(RouteData)都为空
* 3.在控制器的构造函数中,Asp.Net的原始上下文(HttpContext)已经初始化,可以使用
*/
LogHelper.LogHelper _log = new LogHelper.LogHelper();
HttpContext httpCurrent = System.Web.HttpContext.Current;
//测试结果一下都为空
HttpContextBase httpContext = this.HttpContext;
string url = Request == null ? "请求上下文为空" : Request.Url.AbsoluteUri;
_log.WriteLine("当前请求地址:" + url);
string action = RouteData == null ? "路由数据为空" : RouteData.Values["action"].ToString();
_log.WriteLine(string.Format("当前请求控制器:{0},Action:{1}", this.GetType().FullName, RouteData));
}
// GET: Home
public ActionResult Index()
{
//IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
//factory.CreateController();
//factory.ReleaseController()
return View();
}
public ActionResult ShowOne()
{
return View();
}
}
更多: