ASP.NET MVC Preview生命周期分析(三)

详细看看InvokeAction方式的执行:

protected internal bool InvokeAction(string actionName) {
      return InvokeAction (actionName, new RouteValueDictionary());
    }
     protected internal virtual bool InvokeAction(string actionName, RouteValueDictionary values) {
      if (String.IsNullOrEmpty(actionName)) {
        throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
      }
      // We have to loop through all the methods to make sure there isn't
       // a conflict. If we stop the loop the first time we find a match
      // we might miss some error cases.
       MemberInfo[] membInfos = GetType().GetMember(actionName, MemberTypes.Method,
        BindingFlags.IgnoreCase | BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public);
      MethodInfo foundMatch = null;
      foreach (MemberInfo memberInfo in membInfos) {
         MethodInfo mi = (MethodInfo)memberInfo;
         // 1) Action methods must not have the non-action attribute in their inheritance chain, and
        // 2) special methods like constructors, property accessors, and event accessors cannot be action methods, and
        // 3) methods originally defined on Object (like ToString) or Controller cannot be action methods.
         if (!mi.IsDefined(typeof(NonActionAttribute), true) &&
          !mi.IsSpecialName &&
          mi.DeclaringType.IsSubclassOf(typeof(Controller))) {
          if (foundMatch != null) {
             throw new InvalidOperationException(
               String.Format(CultureInfo.CurrentUICulture, MvcResources.Controller_MoreThanOneAction, actionName, GetType()));
          }
          foundMatch = mi;
        }
      }
      if (foundMatch != null) {
        InvokeActionMethod(foundMatch, values);
        return true;
      }
       return false;
    }
它通过反射获取所有同名 Action 方法信 息;其次,它过滤掉所有有 NonActionAttribute 和 IsSpecialName 标记的方法 ;第三,当同名有效 Action 被重载时它会抛出异常(提示 Controller_MoreThanOneAction),继续调用InvokeActionMethod:

[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters",
   Justification = "We use MethodInfo since it represents only methods and not constructors." +
   "This method only makes sense for use with methods.")]
protected internal virtual void InvokeActionMethod(MethodInfo methodInfo, RouteValueDictionary values) {
   if (methodInfo == null) {
     throw new ArgumentNullException("methodInfo");
   }
   if (values == null) {
     values = new RouteValueDictionary();
   }
   if (methodInfo.ContainsGenericParameters) {
     throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, MvcResources.Controller_ActionCannotBeGeneric, methodInfo.Name));
   }
   ParameterInfo[] methodParameters = methodInfo.GetParameters();
   object[] parameterValues = null;
   if (methodParameters.Length > 0) {
     parameterValues = new object[methodParameters.Length];
     for (int i = 0; i < methodParameters.Length; i++) {
        ParameterInfo pi = methodParameters[i];
       if (pi.IsOut || pi.ParameterType.IsByRef) {
         throw new InvalidOperationException(String.Format (CultureInfo.CurrentUICulture, MvcResources.Controller_ReferenceParametersNotSupported, pi.Name, methodInfo.Name));
       }
       bool valueRequired = true;
       if (pi.ParameterType.IsClass) {
         // Classes (ref types) don't require values since we can pass in null
         valueRequired = false;
       }
       else {
          if ((pi.ParameterType.IsGenericType && ! pi.ParameterType.IsGenericTypeDefinition) &&
            (pi.ParameterType.GetGenericTypeDefinition() == typeof (Nullable<>))) {
           // Nullable types don't require values since we can pass in null
            valueRequired = false;
         }
       }
       // Try to get a value for the parameter. We use this order of precedence:
       // 1. Explicitly-provided extra parameters in the call to InvokeAction()
       // 2. Values from the RouteData (could be from the typed-in URL or from the route's default values)
       // 3. Request values (query string, form post data, cookie)
       object parameterValue = null;
       if (!values.TryGetValue (methodParameters[i].Name, out parameterValue)) {
         if (RouteData == null || !RouteData.Values.TryGetValue (methodParameters[i].Name, out parameterValue)) {
            if (Request != null) {
             parameterValue = Request[methodParameters[i].Name];
            }
         }
       }
       if (parameterValue == null && valueRequired) {
          throw new InvalidOperationException(String.Format (CultureInfo.CurrentUICulture, MvcResources.Controller_MissingParameter, pi.Name, methodInfo.Name));
       }
       try {
          parameterValues[i] = ConvertParameterType (parameterValue, methodParameters[i].ParameterType, methodParameters [i].Name, methodInfo.Name);
       }
       catch (Exception ex) {
         // Parameter value conversion errors are acceptable unless the value is required
          if (valueRequired) {
           throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, MvcResources.Controller_MissingParameter, pi.Name, methodInfo.Name), ex);
         }
       }
     }
   }
   InvokeActionMethodFilters(methodInfo, () => methodInfo.Invoke(this, parameterValues));
}

时间: 2024-11-02 12:43:03

ASP.NET MVC Preview生命周期分析(三)的相关文章

ASP.NET MVC Preview生命周期分析(一)

做ASP.NET WebForm开发都知道,ASP.NET有复杂的生命周期,学习ASP.NET MVC就要深入理解它的生命周期.今天从CodePlex上下载了ASP.NET Preview 2 的 源代码,还有两个程序集Routing与Abstractions并未发布,不过这两个程序集的 类并不多,可以用NET反编译工具 Reflector解开来看看,可惜这两个程序集用的 是VS2008使用.net 3.5开发的,用了c# 3.0的很多特性,Reflector反编译不完全 . ASP.NET M

ASP.NET MVC Preview生命周期分析(二)

回到MvcHandler的 ProcessRequest , DefaultControllerFactory.CreateController(RequestContext, requiredString) 来返回 IController 实例.下面看看 DefaultControllerFactory的代码: 通过反射来创建 Controller 实例 ,GetControllerType 里面做了些缓存处理,以此来避免频繁使用反射造成的性 能问题.继续 MvcHandler.Process

ASP.NET AJAX客户端生命周期分析(理论篇)

一.引言 微软的ASP.NET AJAX框架,作为一个相对比较完善的AJAX框架,有许多方面值得我们作深入研究.本文中,我们将结合一个具体的例子试图探究ASP.NET AJAX框架的客户端生命周期过程. [注]阅读本文最好要结合"ASP.NET应用程序生命周期概述"和"ASP.NET页面生命周期概述"两篇文章共同学习. 二.ASP.NET AJAX客户端生命周期原理 因为ASP.NET AJAX框架在开发思路上极大地借鉴了ASP.NET 2.0的开发技术,而且将会被

ASP.NET服务器控件的生命周期分析_实用技巧

本文实例分析了ASP.NET服务器控件的生命周期.分享给大家供大家参考.具体如下: (1)初始化----在此阶段中,主要完成两项工作:一.初始化在传入Web请求生命周期内所需的设置:二.跟踪视图状态.首先,页面框架通过默认方式引发Init事件,并调用OnInit()方法,控件开发人员可以重写该方法为控件提供初始化逻辑.此后,页面框架将调用TrackViewState方法来跟踪视图状态.需要注意的是:多数情况下,Control基类提供的TrackViewState方法实现已经足够了.只有在控件定义

ASP.NET AJAX客户端生命周期分析(实践篇)

一.引言 在上篇中,我们对微软的ASP.NET AJAX框架的客户端生命周期过程作了理论上的分析.在本篇中,我们要结合一个具体示例针对页面的客户端生命周期期间有关重要事件的发生顺序进行剖析. 二.举例 (一)说明 下面的这个例子展示了在一个有两个嵌套的UpdatePanel控件的页面的客户端事件将被如何引发.请注意点击父面板中的按钮与内嵌的UpdatePanel控件中按钮之间的区别.在父面板中的按钮将引起父面板的更新,而嵌在内部的面板将被删除并重新创建.内嵌面板的按钮点击仅引起内嵌面板的更新.

Asp.net页面的生命周期

asp.net|页面 介绍 Asp.net是微软.Net战略的一个组成部分.它相对以前的Asp有了很大的发展,引入了许多的新机制.本文就Asp.net页面的生命周期向大家做一个初步的介绍,以期能起到指导大家更好.更灵活地操纵Asp.net的作用. 当一个获取网页的请求(可能是通过用户提交完成的,也可能是通过超链接完成的)被发送到Web服务器后,这个页面就会接着运行从创建到处理完成的一系列事件.在我们试图建立Asp.net页面的时候,这个执行周期是不必去考虑的,那样只会自讨苦吃.然而,如果被正确的

ASP.NET应用程序生命周期趣谈(一)

这几天一直在看ASP.NET应用程序生命周期,真是太难了,我理解起来费了劲了,但偏偏它又是那么重 要,所以我希望能给大家带来一篇容易理解又好用的文章来帮助学习ASP.NET应用程序生命周期.这篇就 是了. 当你访问博客园想看我的这篇文章的时候,这个请求就被博客园的WEB SERVER(IIS)接收到了.博客 园IIS看了一眼我的请求,"噢,是.aspx啊,给ASP.NET去处理吧,就把我这个请求给了ASP.NET,并且说 :"这个你来处理,你处理完了之后把HTML给我,我好给邱爽一个回

ASP.NET页生命周期和ASP.NET应用程序生命周期有什么不同?

问题描述 ASP.NET页生命周期包括在ASP.NET应用程序生命周期里吗?? 解决方案 解决方案二:http://www.knowsky.com/344806.html你去看看解决方案三:html本身就是所谓statelessprotocol.说到页生命周期时一般是指ViewState.解决方案四:简单讲:ViewState-PageLevelstateSession-SessionLevelstateApplication-ApplicationLevelstate解决方案五:namhyuk

ASP.NET应用程序生命周期问题.

问题描述 看了MSDN上的.ASP.NET应用程序生命周期.有下面几个阶段1.用户从Web服务器请求应用程序资源2.ASP.NET接收对应用程序的第一个请求.3.为每个请求创建ASP.NET核心对象.4.将HttpApplication对象分配给请求5.由HttpApplication管线处理请求.那HttpModule和HttpHandler属于上面的哪个阶段啊? 解决方案 解决方案二:请求-->IIS-->ASP.NETHTTP运行期-->认证-->授权--..........