Asp.Net MVC是否针对每次请求都重新创建一个控制器实例
一、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();
}
}
更多:
Asp.Net MVC是否针对每次请求都重新创建一个控制器实例的更多相关文章
- 简述C#中IO的应用 RabbitMQ安装笔记 一次线上问题引发的对于C#中相等判断的思考 ef和mysql使用(一) ASP.NET/MVC/Core的HTTP请求流程
简述C#中IO的应用 在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.I ...
- ASP.NET MVC学前篇之请求流程
ASP.NET MVC学前篇之请求流程 请求流程描述 对于请求的流程,文章的重点是讲HttpApplication和HttpModule之间的关系,以及一个简单的示例实现.(HttpModule又是M ...
- 【nodejs】让nodejs像后端mvc框架(asp.net mvc)一样处理请求--目录(8/8 完结)
为什么要做这个 在使用nodejs开发过程中,总是发现需要做很多重复性的体力劳动,且因为自身是服务端程序员出身,感觉有一些服务端好的东西其实可以在nodejs上得到应用并能提高一些开发工作效率. 本系 ...
- ASP.NET MVC 防止跨站请求伪造(CSRF)攻击的方法
在HTTP POST请求中,我们多次在View和Controller中看下如下代码: View中调用了Html.AntiForgeryToken(). Controller中的方法添加了[Valida ...
- ASP.NET Core 如何记录每次请求的Request信息 - sky 胡萝卜星星 - CSDN博客
原文:ASP.NET Core 如何记录每次请求的Request信息 - sky 胡萝卜星星 - CSDN博客 版权声明:本文为starfd原创文章,转载请标明出处. https://blog.csd ...
- ASP.NET MVC基于标注特性的Model验证:一个Model,多种验证规则
原文:ASP.NET MVC基于标注特性的Model验证:一个Model,多种验证规则 对于Model验证,理想的设计应该是场景驱动的,而不是Model(类型)驱动的,也就是对于同一个Model对象, ...
- 【翻译转载】【官方教程】Asp.Net MVC4入门指南(2):添加一个控制器
2. 添加一个控制器 · 原文地址:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-c ...
- Asp.Net MVC4入门指南(2):添加一个控制器
MVC代表: 模型-视图-控制器 .MVC是一个架构良好并且易于测试和易于维护的开发模式.基于MVC模式的应用程序包含: · Models: 表示该应用程序的数据并使用验证逻辑来强制实施业务规则的数据 ...
- 【ASP.NET Web API教程】2.3.3 创建Admin控制器
原文:[ASP.NET Web API教程]2.3.3 创建Admin控制器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. Part 3 ...
随机推荐
- C# GC.Collect()
用C#写了一个运用ICE组件进行接口通信的服务程序,程序运行很正常,可是在客户端调用ICE接口时出现了大量的数据丢失,而且偶尔还通信不上,服务端最明显的现象就是telnet服务的通信端口时不通(cmd ...
- Android学习笔记(1)—Android Studio安装
Android Studio 是一个全新的 Android 开发环境,基于IntelliJ IDEA. 类似 Eclipse ADT,Android Studio 提供了集成的 Android 开发工 ...
- BestCoder Round #81 (div.1)A
水题...就是n的三进制后m位 #include<cstdio> #include<cstring> #include<cstdlib> #include<i ...
- Codevs 1222 信与信封问题 二分图匹配,匈牙利算法
题目: http://codevs.cn/problem/1222/ 1222 信与信封问题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 ...
- Msys下gcc的配置
打开文件/etc/profile,添加如下路径, C_INCLUDE_PATH=/e/msys/1.0/include export C_INCLUDE_PATH CPLUS_INCLUDE_PATH ...
- 在YII中使用Redis等缓存
Yii AR 单行数据-自动缓存机制 | LOCKPHP Yii AR 单行数据-自动LOG机制 CActiveRecordBehavior进阶 | LOCKPHP 缓存 - 权威指南 - Yii F ...
- Asp.net多行文本框随内容增加而高度增加
最近做一个项目,在一个多行文本框(TextBox)里显示新闻内容,由于内容有多有少,并且总是出现垂直滚动条,很不好看,笔者就想用一个法子,去掉垂直滚动条,并且文本框的高度随内容的增加而变大,使高度适应 ...
- oracle中使用sql查询时字段为空则赋值默认
转至:http://www.th7.cn/db/Oracle/201501/86125.shtml oracle 通过 nvl( )函数sql 查询时为 空值 赋默认值 oracle 函数介绍之nvl ...
- [GIF] GIF Loop Coder - Interpolation
This video discusses the default interpolation in GIF Loop Coder, and four distinct ways to change t ...
- Hdu 2473(并查集删除操作) Junk-Mail Filter
有木有非常吊 加强 加强版 啊 ,看了都不敢做了 .后来先做了食物链这个我还是看过的.但还是A不掉,没明确神魔意思 .总而言之.大牛的博客是个好东西.我就那么看了一下,还是不懂怎莫办啊,哎, ...