标签:des style http color 使用 os strong io
上篇讲到 请求到达 MvcRouteHandler ,并且透过 IRouteHandler.GetHttpHandler 获取到了真正的处理程序 MvcHandler
这次我们看看,MvcHandler是如何依据请求,来激活对应的controller和Action来处理请求的。
一、先看看MvcHandler 的核心内容
1: public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
2: {3: protected virtual void ProcessRequest(HttpContext httpContext)
4: {5: //使用HttpContextWrapper对HttpContext进行封装,封装的目的是为了解耦以获得可测试性.然后从RequestContext.RouteData中提取Controller名称.
6: HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
7: this.ProcessRequest(httpContext2);
8: } 9: 10: protected internal virtual void ProcessRequest(HttpContextBase httpContext)
11: { 12: IController controller; 13: IControllerFactory controllerFactory;14: this.ProcessRequestInit(httpContext, out controller, out controllerFactory);//获取到Controler和ControllerFactory实例,并赋值给局部变量
15: try
16: {17: //Action的调用,下一篇介绍
18: //当前Controler对象的Action的创建与执行(执行包括:加载TempData, 创建及执行Action,处理Action返回的ActionResult ,保存TempData数据)
19: controller.Execute(this.RequestContext);
20: 21: }22: finally
23: {24: //释放当前Controler对象
25: controllerFactory.ReleaseController(controller); 26: } 27: } 28: }
从上述代码中可以看出,对Controller激活的相关的操作是通过MvcHandler类的 ProcessRequestInit 方法来执行,而执行完成后,将获取到Controller和ControllerFactory实例。
this.ProcessRequestInit(httpContext, out controller, out controllerFactory) ,下面就通过这个方法的内部代码来剖析下Controller的激活的机制
1: private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
2: { 3: 4: // If request validation has already been enabled, make it lazy. This allows attributes like [HttpPost] (which looks
5: // at Request.Form) to work correctly without triggering full validation.
6: // Tolerate null HttpContext for testing.
7: //看不明白
8: HttpContext currentContext = HttpContext.Current;9: if (currentContext != null)
10: {11: bool? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(currentContext);
12: if (isRequestValidationEnabled == true)
13: { 14: ValidationUtility.EnableDynamicValidation(currentContext); 15: } 16: }17: //为响应添加特定的头标示:MvcVersionHeaderName, MvcVersion
18: AddVersionHeader(httpContext);19: //从当前请求的路由集合中,移除可选的路由参数
20: RemoveOptionalRoutingParameters(); 21: 22: // Get the controller type
23: //从当前请求的路由集合中,检索名为"controller"参数的值
24: string controllerName = RequestContext.RouteData.GetRequiredString("controller");
25: 26: // Instantiate the controller and call Execute
27: //通过 ControllerBuilder 获取 当前的 controllFactory 控制器工厂
28: factory = ControllerBuilder.GetControllerFactory();29: //通过controllFactory 控制器工厂 ,以及前边获取到的 controllerName,构建一个 controller类型实例。
30: controller = factory.CreateController(RequestContext, controllerName);31: if (controller == null)
32: {33: throw new InvalidOperationException(
34: String.Format( 35: CultureInfo.CurrentCulture, 36: MvcResources.ControllerBuilder_FactoryReturnedNull, 37: factory.GetType(), 38: controllerName)); 39: } 40: } 41:
由于使用了out关键字,这个方法中的执行过程中所得到的值,即:赋值给ProcessRequest方法中声明的Controller和ControllerFactory
以下是没有搞清楚的内容,如何获取工厂,工厂又如何依据名字,创建一个controller类型实例。
显然,上述的代码中有两行重要代码:
1、factory = this.ControllerBuilder.GetControllerFactory();
this.ControllerBuilder是MvcHandler类的一个属性,属性返回的是MvcHandler类声明的一个 ControllerBuilder类型的字段,属性在返回时会判断当前字段是否为空,如果为空,则调用ControllerBuilder类的静态属性 Current字段,来获取一个ControllerBuilder实例。
接下来再看一下ControllerBuilder类
1: namespace System.Web.Mvc
2: {3: public class ControllerBuilder
4: {5: //声明静态字段,执行此类的构造函数
6: private static ControllerBuilder _instance = new ControllerBuilder();
7: 8: private Func<IControllerFactory> _factoryThunk = () => null;
9: private HashSet<string> _namespaces = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
10: 11: //暂且理解为是封装ControllerFactory的一个类,通过该类的Current属性来获取当前封装的ControllerFactory实例
12: private IResolver<IControllerFactory> _serviceResolver;
13: 14: public ControllerBuilder()
15: : this(null) //: this(null)表示执行带一个参数的构造函数,并且传入的参数为Null
16: { 17: } 18: 19: internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)
20: {21: //如果传入的参数为null,则实例化一个SingleServiceResolver类并赋值给私有字段_serviceResolver。
22: _serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
23: () => _factoryThunk(),24: new DefaultControllerFactory { ControllerBuilder = this },
25: "ControllerBuilder.GetControllerFactory");
26: } 27: 28: public static ControllerBuilder Current
29: {30: //获取Controller实例
31: get { return _instance; }
32: } 33: 34: public HashSet<string> DefaultNamespaces
35: {36: get { return _namespaces; }
37: } 38: 39: [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Calling method multiple times might return different objects.")]
40: public IControllerFactory GetControllerFactory()
41: {42: //获取ControllerFactory实例
43: return _serviceResolver.Current;
44: } 45: 46: public void SetControllerFactory(IControllerFactory controllerFactory)
47: {48: if (controllerFactory == null)
49: {50: throw new ArgumentNullException("controllerFactory");
51: } 52: 53: _factoryThunk = () => controllerFactory; 54: } 55: 56: public void SetControllerFactory(Type controllerFactoryType)
57: {58: if (controllerFactoryType == null)
59: {60: throw new ArgumentNullException("controllerFactoryType");
61: }62: if (!typeof(IControllerFactory).IsAssignableFrom(controllerFactoryType))
63: {64: throw new ArgumentException(
65: String.Format( 66: CultureInfo.CurrentCulture, 67: MvcResources.ControllerBuilder_MissingIControllerFactory, 68: controllerFactoryType),69: "controllerFactoryType");
70: } 71: 72: _factoryThunk = delegate
73: {74: try
75: {76: return (IControllerFactory)Activator.CreateInstance(controllerFactoryType);
77: }78: catch (Exception ex)
79: {80: throw new InvalidOperationException(
81: String.Format( 82: CultureInfo.CurrentCulture, 83: MvcResources.ControllerBuilder_ErrorCreatingControllerFactory, 84: controllerFactoryType), 85: ex); 86: } 87: }; 88: } 89: } 90: }
2、controller = factory.CreateController(this.RequestContext, controllername);
此行代码,利用上一句得到一个ControllerFactory实例。将 RequestContext 和Controllername作为参数来调用 ControllerFactory类的CreateController方法,以此创建Controller实例并返回。
至此,我们从请求的 路由数据中,得到 controllerName,又用controllerName,通过 ControllerFactory 获取到了真正的 Controller。
????
004. Asp.Net Routing与MVC 之二: 请求如何激活Controller和Action,布布扣,bubuko.com
004. Asp.Net Routing与MVC 之二: 请求如何激活Controller和Action
标签:des style http color 使用 os strong io
原文地址:http://www.cnblogs.com/acejason/p/3886968.html