一、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--Controller激活2

ASP.NET MVC——Controller的激活

关于上下文

Asp.Net MVC是否针对每次请求都重新创建一个控制器实例的更多相关文章

  1. 简述C#中IO的应用 RabbitMQ安装笔记 一次线上问题引发的对于C#中相等判断的思考 ef和mysql使用(一) ASP.NET/MVC/Core的HTTP请求流程

    简述C#中IO的应用   在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.I ...

  2. ASP.NET MVC学前篇之请求流程

    ASP.NET MVC学前篇之请求流程 请求流程描述 对于请求的流程,文章的重点是讲HttpApplication和HttpModule之间的关系,以及一个简单的示例实现.(HttpModule又是M ...

  3. 【nodejs】让nodejs像后端mvc框架(asp.net mvc)一样处理请求--目录(8/8 完结)

    为什么要做这个 在使用nodejs开发过程中,总是发现需要做很多重复性的体力劳动,且因为自身是服务端程序员出身,感觉有一些服务端好的东西其实可以在nodejs上得到应用并能提高一些开发工作效率. 本系 ...

  4. ASP.NET MVC 防止跨站请求伪造(CSRF)攻击的方法

    在HTTP POST请求中,我们多次在View和Controller中看下如下代码: View中调用了Html.AntiForgeryToken(). Controller中的方法添加了[Valida ...

  5. ASP.NET Core 如何记录每次请求的Request信息 - sky 胡萝卜星星 - CSDN博客

    原文:ASP.NET Core 如何记录每次请求的Request信息 - sky 胡萝卜星星 - CSDN博客 版权声明:本文为starfd原创文章,转载请标明出处. https://blog.csd ...

  6. ASP.NET MVC基于标注特性的Model验证:一个Model,多种验证规则

    原文:ASP.NET MVC基于标注特性的Model验证:一个Model,多种验证规则 对于Model验证,理想的设计应该是场景驱动的,而不是Model(类型)驱动的,也就是对于同一个Model对象, ...

  7. 【翻译转载】【官方教程】Asp.Net MVC4入门指南(2):添加一个控制器

    2. 添加一个控制器 · 原文地址:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-c ...

  8. Asp.Net MVC4入门指南(2):添加一个控制器

    MVC代表: 模型-视图-控制器 .MVC是一个架构良好并且易于测试和易于维护的开发模式.基于MVC模式的应用程序包含: · Models: 表示该应用程序的数据并使用验证逻辑来强制实施业务规则的数据 ...

  9. 【ASP.NET Web API教程】2.3.3 创建Admin控制器

    原文:[ASP.NET Web API教程]2.3.3 创建Admin控制器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. Part 3 ...

随机推荐

  1. How to Set Word Document Properties with C#

    Word properties shows a brief description about one document. Through properties, we can learn gener ...

  2. Linux下的nginx启动、重新启动

    nginx的启动命令是: /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf -c制定配置文件的路径,不加-nginx会自动 ...

  3. Get ListView items from other windows z

    This is more difficult than one might think. In order to get the information you're looking for, you ...

  4. Test Controller Tool

  5. Spring_Springmvc_mybatis一般配置

    web.xml配置 <?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi=&quo ...

  6. Weka 入门3

    这次我们介绍Evaluation类.在上一次中我们只是单纯的预测了分类值,并没有其他评价数据.这场我们使用Evalution类.首先初始化一个Evaluation对象,Evaluation类没有无参的 ...

  7. Android核心基础(四)

    1.联系人表结构 添加一条联系人信息 package com.itheima.insertcontact; import android.app.Activity; import android.co ...

  8. Excel引用

    Excel引用 1.绝对引用  相对引用 A:A   左右拉的话会自动变为  B:B,C:C等等 $A:$A  左右拉的话仍然是A列 A$1:A1  上下拉的话,会变成A$1:A2,A$1:A3等等

  9. 编写Word宏使选中的图片改变为固定宽度并保持纵横比

    代码如下: Sub 改变图片宽度为12并设置灰色边框() ' ' 改变图片宽度为12并设置灰色边框 宏 ' '     ' Application.Run MacroName:="改变图片大 ...

  10. JBPM流程实例(PI)Process Instance

    /** * 流程实例 *    *  启动流程实例 *    *  完成任务 *    *  查询 *      *  查询流程实例 *      *  查询任务 *          *  查询正在 ...