MVC ASP.net流程 源代码分析

AppDomainFactory.cs

1. public Object Create(String appId, String appPath)

 public Object Create(String appId, String appPath) {
            try {
                //
                //  Fill app a Dictionary with 'binding rules' -- name value string pairs
                //  for app domain creation
                //

                // 


                if (appPath[0] == '.') {
                    System.IO.FileInfo file = new System.IO.FileInfo(appPath);
                    appPath = file.FullName;
                }

                if (!StringUtil.StringEndsWith(appPath, '\\')) {
                    appPath = appPath + "\\";
                }

                // Create new app domain via App Manager
#if FEATURE_PAL // FEATURE_PAL does not enable IIS-based hosting features
                throw new NotImplementedException("ROTORTODO");
#else // FEATURE_PAL 

//创建应用程序域 ISAPIApplicationHost appHost
= new ISAPIApplicationHost(appId, appPath, false /*validatePhysicalPath*/);
//创建ISAPIRuntime ISAPIRuntime isapiRuntime
= (ISAPIRuntime)_appManager.CreateObjectInternal(appId, typeof(ISAPIRuntime), appHost, false /*failIfExists*/, null /*hostingParameters*/); isapiRuntime.StartProcessing(); return new ObjectHandle(isapiRuntime); #endif // FEATURE_PAL } catch (Exception e) { Debug.Trace("internal", "AppDomainFactory::Create failed with " + e.GetType().FullName + ": " + e.Message + "\r\n" + e.StackTrace); throw; } }

 

2.appManager.Create._appManager.CreateObjectInternal
 internal IRegisteredObject CreateObjectInternal(
                                        String appId,
                                        Type type,
                                        IApplicationHost appHost,
                                        bool failIfExists,
                                        HostingEnvironmentParameters hostingParameters) {

            // check that type is as IRegisteredObject
            if (!typeof(IRegisteredObject).IsAssignableFrom(type))
                throw new ArgumentException(SR.GetString(SR.Not_IRegisteredObject, type.FullName), "type");

            // get hosting environment 创建宿主环境
            HostingEnvironment env = GetAppDomainWithHostingEnvironment(appId, appHost, hostingParameters);

            // create the managed object in the worker app domain
            // When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not
            // always the case, so we marshal the assembly qualified name instead
            ObjectHandle h = env.CreateWellKnownObjectInstance(type.AssemblyQualifiedName, failIfExists);
            return (h != null) ? h.Unwrap() as IRegisteredObject : null;
        }
ISAPIRuntime 

public int ProcessRequest(IntPtr ecb, int iWRType) {
            IntPtr pHttpCompletion = IntPtr.Zero;
            if (iWRType == WORKER_REQUEST_TYPE_IN_PROC_VERSION_2) {
                pHttpCompletion = ecb;
                ecb = UnsafeNativeMethods.GetEcb(pHttpCompletion);
            } 
            ISAPIWorkerRequest wr = null;
            try {
                bool useOOP = (iWRType == WORKER_REQUEST_TYPE_OOP);
                wr = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP);
                wr.Initialize();

                // check if app path matches (need to restart app domain?)                
                String wrPath = wr.GetAppPathTranslated();
                String adPath = HttpRuntime.AppDomainAppPathInternal;                
                
                if (adPath == null ||
                    StringUtil.EqualsIgnoreCase(wrPath, adPath)) {
                    
                    HttpRuntime.ProcessRequestNoDemand(wr);
                    return 0;
                }
                else {
                    // need to restart app domain
                    HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged,
                                                  SR.GetString(SR.Hosting_Phys_Path_Changed,
                                                                                   adPath,
                                                                                   wrPath));
                    return 1;
                }
            }
            catch(Exception e) {
                try {
                    WebBaseEvent.RaiseRuntimeError(e, this);
                } catch {}
                
                // Have we called HSE_REQ_DONE_WITH_SESSION?  If so, don't re-throw.
                if (wr != null && wr.Ecb == IntPtr.Zero) {
                    if (pHttpCompletion != IntPtr.Zero) {
                        UnsafeNativeMethods.SetDoneWithSessionCalled(pHttpCompletion);
                    }
                    // if this is a thread abort exception, cancel the abort
                    if (e is ThreadAbortException) {
                        Thread.ResetAbort();
                    }                    
                    // IMPORTANT: if this thread is being aborted because of an AppDomain.Unload,
                    // the CLR will still throw an AppDomainUnloadedException. The native caller
                    // must special case COR_E_APPDOMAINUNLOADED(0x80131014) and not
                    // call HSE_REQ_DONE_WITH_SESSION more than once.
                    return 0;
                }
                
                // re-throw if we have not called HSE_REQ_DONE_WITH_SESSION
                throw;
            }
        }

 

HttpRuntime

1.ProcessRequestNow().ProcessRequestInternal()

1.创建HttpContext
2.向HttpApplicationFactory类的一个实例申请一个HttpApplication
3.调用HttpApplication的InitalModule

 private void ProcessRequestInternal(HttpWorkerRequest wr) {
            // Count active requests
            Interlocked.Increment(ref _activeRequestCount);

            if (_disposingHttpRuntime) {
                // Dev11 333176: An appdomain is unloaded before all requests are served, resulting in System.AppDomainUnloadedException during isapi completion callback
                //
                // HttpRuntim.Dispose could have already finished on a different thread when we had no active requests
                // In this case we are about to start or already started unloading the appdomain so we will reject the request the safest way possible
                try {
                    wr.SendStatus(503, "Server Too Busy");
                    wr.SendKnownResponseHeader(HttpWorkerRequest.HeaderContentType, "text/html; charset=utf-8");
                    byte[] body = Encoding.ASCII.GetBytes("<html><body>Server Too Busy</body></html>");
                    wr.SendResponseFromMemory(body, body.Length);
                    // this will flush synchronously because of HttpRuntime.ShutdownInProgress
                    wr.FlushResponse(true);
                    wr.EndOfRequest();
                } finally {
                    Interlocked.Decrement(ref _activeRequestCount);
                }
                return;
            }

            // Construct the Context on HttpWorkerRequest, hook everything together
            HttpContext context;

            try {
                context = new HttpContext(wr, false /* initResponseWriter */);
            } 
            catch {
                try {
                    // If we fail to create the context for any reason, send back a 400 to make sure
                    // the request is correctly closed (relates to VSUQFE3962)
                    wr.SendStatus(400, "Bad Request");
                    wr.SendKnownResponseHeader(HttpWorkerRequest.HeaderContentType, "text/html; charset=utf-8");
                    byte[] body = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");
                    wr.SendResponseFromMemory(body, body.Length);
                    wr.FlushResponse(true);
                    wr.EndOfRequest();
                    return;
                } finally {
                    Interlocked.Decrement(ref _activeRequestCount);
                }
            }

            wr.SetEndOfSendNotification(_asyncEndOfSendCallback, context);

            HostingEnvironment.IncrementBusyCount();

            try {
                // First request initialization
                try {
                    EnsureFirstRequestInit(context);
                }
                catch {
                    // If we are handling a DEBUG request, ignore the FirstRequestInit exception.
                    // This allows the HttpDebugHandler to execute, and lets the debugger attach to
                    // the process (VSWhidbey 358135)
                    if (!context.Request.IsDebuggingRequest) {
                        throw;
                    }
                }

                // Init response writer (after we have config in first request init)
                // no need for impersonation as it is handled in config system
                context.Response.InitResponseWriter();

                // Get application instance
                IHttpHandler app = HttpApplicationFactory.GetApplicationInstance(context);

                if (app == null)
                    throw new HttpException(SR.GetString(SR.Unable_create_app_object));

                if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, app.GetType().FullName, "Start");

                if (app is IHttpAsyncHandler) {
                    // asynchronous handler
                    IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler)app;
                    context.AsyncAppHandler = asyncHandler;
                    asyncHandler.BeginProcessRequest(context, _handlerCompletionCallback, context);
                }
                else {
                    // synchronous handler
                    app.ProcessRequest(context);
                    FinishRequest(context.WorkerRequest, context, null);
                }
            }
            catch (Exception e) {
                context.Response.InitResponseWriter();
                FinishRequest(wr, context, e);
            }
        }

 

IHttpHandler app = HttpApplicationFactory.GetApplicationInstance(context);

   internal static IHttpHandler GetApplicationInstance(HttpContext context) {
            if (_customApplication != null)
                return _customApplication;

            // Check to see if it's a debug auto-attach request
            if (context.Request.IsDebuggingRequest)
                return new HttpDebugHandler();

            _theApplicationFactory.EnsureInited();

            _theApplicationFactory.EnsureAppStartCalled(context);

            return _theApplicationFactory.GetNormalApplicationInstance(context);
        }


 private HttpApplication GetNormalApplicationInstance(HttpContext context) {
            HttpApplication app = null;

            lock (_freeList) {
                if (_numFreeAppInstances > 0) {
                    app = (HttpApplication)_freeList.Pop();
                    _numFreeAppInstances--;

                    if (_numFreeAppInstances < _minFreeAppInstances) {
                        _minFreeAppInstances = _numFreeAppInstances;
                    }
                }
            }

            if (app == null) {
                // If ran out of instances, create a new one
                app = (HttpApplication)HttpRuntime.CreateNonPublicInstance(_theApplicationType);

                using (new ApplicationImpersonationContext()) {
                    app.InitInternal(context, _state, _eventHandlerMethods);
                }
            }

            if (AppSettings.UseTaskFriendlySynchronizationContext) {
                // When this HttpApplication instance is no longer in use, recycle it.
                app.ApplicationInstanceConsumersCounter = new CountdownTask(1); // representing required call to HttpApplication.ReleaseAppInstance
                app.ApplicationInstanceConsumersCounter.Task.ContinueWith((_, o) => RecycleApplicationInstance((HttpApplication)o), app, TaskContinuationOptions.ExecuteSynchronously);
            }
            return app;
        }

 

 

 

 

 

HttpApplication

  internal void InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers) {
            Debug.Assert(context != null, "context != null");

            // Remember state
            _state = state;

            PerfCounters.IncrementCounter(AppPerfCounter.PIPELINES);

            try {
                try {
                    // Remember context for config lookups
                    _initContext = context;
                    _initContext.ApplicationInstance = this;

                    // Set config path to be application path for the application initialization
                    context.ConfigurationPath = context.Request.ApplicationPathObject;

                    // keep HttpContext.Current working while running user code
                    using (new DisposableHttpContextWrapper(context)) {

                        // Build module list from config
                        if (HttpRuntime.UseIntegratedPipeline) {

                            Debug.Assert(_moduleConfigInfo != null, "_moduleConfigInfo != null");
                            Debug.Assert(_moduleConfigInfo.Count >= 0, "_moduleConfigInfo.Count >= 0");

                            try {
                                context.HideRequestResponse = true;
                                _hideRequestResponse = true;
                                InitIntegratedModules();
                            }
                            finally {
                                context.HideRequestResponse = false;
                                _hideRequestResponse = false;
                            }
                        }
                        else {
                            InitModules();

                            // this is used exclusively for integrated mode
                            Debug.Assert(null == _moduleContainers, "null == _moduleContainers");
                        }

                        // Hookup event handlers via reflection
                        if (handlers != null)
                            HookupEventHandlersForApplicationAndModules(handlers);

                        // Initialization of the derived class
                        _context = context;
                        if (HttpRuntime.UseIntegratedPipeline && _context != null) {
                            _context.HideRequestResponse = true;
                        }
                        _hideRequestResponse = true;

                        try {
                            Init();
                        }
                        catch (Exception e) {
                            RecordError(e);
                        }
                    }

                    if (HttpRuntime.UseIntegratedPipeline && _context != null) {
                        _context.HideRequestResponse = false;
                    }
                    _hideRequestResponse = false;
                    _context = null;
                    _resumeStepsWaitCallback= new WaitCallback(this.ResumeStepsWaitCallback);

                    // Construct the execution steps array
                    if (HttpRuntime.UseIntegratedPipeline) {
                        _stepManager = new PipelineStepManager(this);
                    }
                    else {
                        _stepManager = new ApplicationStepManager(this);
                    }

                    _stepManager.BuildSteps(_resumeStepsWaitCallback);
                }
                finally {
                    _initInternalCompleted = true;

                    // Reset config path
                    context.ConfigurationPath = null;

                    // don't hold on to the context
                    _initContext.ApplicationInstance = null;
                    _initContext = null;
                }
            }
            catch { // Protect against exception filters
                throw;
            }
        }

 

   private void HookupEventHandlersForApplicationAndModules(MethodInfo[] handlers) {
            _currentModuleCollectionKey = HttpApplicationFactory.applicationFileName;

            if(null == _pipelineEventMasks) {
                Dictionary<string, RequestNotification> dict = new Dictionary<string, RequestNotification>();
                BuildEventMaskDictionary(dict);
                if(null == _pipelineEventMasks) {
                    _pipelineEventMasks = dict;
                }
            }


            for (int i = 0; i < handlers.Length; i++) {
                MethodInfo appMethod = handlers[i];
                String appMethodName = appMethod.Name;
                int namePosIndex = appMethodName.IndexOf('_');
                String targetName = appMethodName.Substring(0, namePosIndex);

                // Find target for method
                Object target = null;

                if (StringUtil.EqualsIgnoreCase(targetName, "Application"))
                    target = this;
                else if (_moduleCollection != null)
                    target = _moduleCollection[targetName];

                if (target == null)
                    continue;

                // Find event on the module type
                Type targetType = target.GetType();
                EventDescriptorCollection events = TypeDescriptor.GetEvents(targetType);
                string eventName = appMethodName.Substring(namePosIndex+1);

                EventDescriptor foundEvent = events.Find(eventName, true);
                if (foundEvent == null
                    && StringUtil.EqualsIgnoreCase(eventName.Substring(0, 2), "on")) {

                    eventName = eventName.Substring(2);
                    foundEvent = events.Find(eventName, true);
                }

                MethodInfo addMethod = null;
                if (foundEvent != null) {
                    EventInfo reflectionEvent = targetType.GetEvent(foundEvent.Name);
                    Debug.Assert(reflectionEvent != null);
                    if (reflectionEvent != null) {
                        addMethod = reflectionEvent.GetAddMethod();
                    }
                }

                if (addMethod == null)
                    continue;

                ParameterInfo[] addMethodParams = addMethod.GetParameters();

                if (addMethodParams.Length != 1)
                    continue;

                // Create the delegate from app method to pass to AddXXX(handler) method

                Delegate handlerDelegate = null;

                ParameterInfo[] appMethodParams = appMethod.GetParameters();

                if (appMethodParams.Length == 0) {
                    // If the app method doesn't have arguments --
                    // -- hookup via intermidiate handler

                    // only can do it for EventHandler, not strongly typed
                    if (addMethodParams[0].ParameterType != typeof(System.EventHandler))
                        continue;

                    ArglessEventHandlerProxy proxy = new ArglessEventHandlerProxy(this, appMethod);
                    handlerDelegate = proxy.Handler;
                }
                else {
                    // Hookup directly to the app methods hoping all types match

                    try {
                        handlerDelegate = Delegate.CreateDelegate(addMethodParams[0].ParameterType, this, appMethodName);
                    }
                    catch {
                        // some type mismatch
                        continue;
                    }
                }

                // Call the AddXXX() to hook up the delegate

                try {
                    addMethod.Invoke(target, new Object[1]{handlerDelegate});
                }
                catch {
                    if (HttpRuntime.UseIntegratedPipeline) {
                        throw;
                    }
                }

                if (eventName != null) {
                    if (_pipelineEventMasks.ContainsKey(eventName)) {
                        if (!StringUtil.StringStartsWith(eventName, "Post")) {
                            _appRequestNotifications |= _pipelineEventMasks[eventName];
                        }
                        else {
                            _appPostNotifications |= _pipelineEventMasks[eventName];
                        }
                    }
                }
            }
        }

 




private void RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) { RequestNotification requestNotifications; RequestNotification postRequestNotifications; // register an implicit filter module RegisterIntegratedEvent(appContext, IMPLICIT_FILTER_MODULE, RequestNotification.UpdateRequestCache| RequestNotification.LogRequest /*requestNotifications*/, 0 /*postRequestNotifications*/, String.Empty /*type*/, String.Empty /*precondition*/, true /*useHighPriority*/); // integrated pipeline will always use serverModules instead of <httpModules> _moduleCollection = GetModuleCollection(appContext); if (handlers != null) { HookupEventHandlersForApplicationAndModules(handlers); } // 1643363: Breaking Change: ASP.Net v2.0: Application_OnStart is called after Module.Init (Integarted mode) HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(context, this); // Call Init on HttpApplication derived class ("global.asax") // and process event subscriptions before processing other modules. // Doing this now prevents clearing any events that may // have been added to event handlers during instantiation of this instance. // NOTE: If "global.asax" has a constructor which hooks up event handlers, // then they were added to the event handler lists but have not been registered with IIS yet, // so we MUST call ProcessEventSubscriptions on it first, before the other modules. _currentModuleCollectionKey = HttpApplicationFactory.applicationFileName; try { _hideRequestResponse = true; context.HideRequestResponse = true; _context = context; Init(); } catch (Exception e) { RecordError(e); Exception error = context.Error; if (error != null) { throw error; } } finally { _context = null; context.HideRequestResponse = false; _hideRequestResponse = false; } ProcessEventSubscriptions(out requestNotifications, out postRequestNotifications); // Save the notification subscriptions so we can register them with IIS later, after // we call HookupEventHandlersForApplicationAndModules and process global.asax event handlers. _appRequestNotifications |= requestNotifications; _appPostNotifications |= postRequestNotifications; for (int i = 0; i < _moduleCollection.Count; i++) { _currentModuleCollectionKey = _moduleCollection.GetKey(i); IHttpModule httpModule = _moduleCollection.Get(i); ModuleConfigurationInfo moduleInfo = _moduleConfigInfo[i]; #if DBG Debug.Trace("PipelineRuntime", "RegisterEventSubscriptionsWithIIS: name=" + CurrentModuleCollectionKey + ", type=" + httpModule.GetType().FullName + "\n"); // make sure collections are in sync Debug.Assert(moduleInfo.Name == _currentModuleCollectionKey, "moduleInfo.Name == _currentModuleCollectionKey"); #endif httpModule.Init(this); ProcessEventSubscriptions(out requestNotifications, out postRequestNotifications); // are any events wired up? if (requestNotifications != 0 || postRequestNotifications != 0) { RegisterIntegratedEvent(appContext, moduleInfo.Name, requestNotifications, postRequestNotifications, moduleInfo.Type, moduleInfo.Precondition, false /*useHighPriority*/); } } // WOS 1728067: RewritePath does not remap the handler when rewriting from a non-ASP.NET request // register a default implicit handler RegisterIntegratedEvent(appContext, IMPLICIT_HANDLER, RequestNotification.ExecuteRequestHandler | RequestNotification.MapRequestHandler /*requestNotifications*/, RequestNotification.EndRequest /*postRequestNotifications*/, String.Empty /*type*/, String.Empty /*precondition*/, false /*useHighPriority*/); }

 

 

UrlRoutingModule
 protected virtual void Init(HttpApplication application) {

            //////////////////////////////////////////////////////////////////
            // Check if this module has been already addded
            if (application.Context.Items[_contextKey] != null) {
                return; // already added to the pipeline
            }
            application.Context.Items[_contextKey] = _contextKey;

            // Ideally we would use the MapRequestHandler event.  However, MapRequestHandler is not available
            // in II6 or IIS7 ISAPI Mode.  Instead, we use PostResolveRequestCache, which is the event immediately
            // before MapRequestHandler.  This allows use to use one common codepath for all versions of IIS.
            application.PostResolveRequestCache += OnApplicationPostResolveRequestCache;
        }

 



public virtual void PostResolveRequestCache(HttpContextBase context) { // Match the incoming URL against the route table RouteData routeData = RouteCollection.GetRouteData(context); // Do nothing if no route found if (routeData == null) { return; } // If a route was found, get an IHttpHandler from the route's RouteHandler IRouteHandler routeHandler = routeData.RouteHandler; if (routeHandler == null) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, SR.GetString(SR.UrlRoutingModule_NoRouteHandler))); } // This is a special IRouteHandler that tells the routing module to stop processing // routes and to let the fallback handler handle the request. if (routeHandler is StopRoutingHandler) { return; } RequestContext requestContext = new RequestContext(context, routeData); // Dev10 766875 Adding RouteData to HttpContext context.Request.RequestContext = requestContext; IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);//创建MVCHandler 并将RequestContext存入
if (httpHandler == null) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentUICulture, SR.GetString(SR.UrlRoutingModule_NoHttpHandler), routeHandler.GetType())); } if (httpHandler is UrlAuthFailureHandler) { if (FormsAuthenticationModule.FormsAuthRequired) { UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this); return; } else { throw new HttpException(401, SR.GetString(SR.Assess_Denied_Description3)); } } // Remap IIS7 to our handler context.RemapHandler(httpHandler);//将MVCHandler存入HttpContext对象 }

 

 

RouteData routeData = RouteCollection.GetRouteData(context)

RouteCollection

 

 public RouteData GetRouteData(HttpContextBase httpContext) {
            if (httpContext == null) {
                throw new ArgumentNullException("httpContext");
            }
            if (httpContext.Request == null) {
                throw new ArgumentException(SR.GetString(SR.RouteTable_ContextMissingRequest), "httpContext");
            }

            // Optimize performance when the route collection is empty.  The main improvement is that we avoid taking
            // a read lock when the collection is empty.  Without this check, the UrlRoutingModule causes a 25%-50%
            // regression in HelloWorld RPS due to lock contention.  The UrlRoutingModule is now in the root web.config,
            // so we need to ensure the module is performant, especially when you are not using routing.
            // This check does introduce a slight 


            if (Count == 0) {
                return null;
            }

            bool isRouteToExistingFile = false;
            bool doneRouteCheck = false; // We only want to do the route check once
            if (!RouteExistingFiles) {
                isRouteToExistingFile = IsRouteToExistingFile(httpContext);
                doneRouteCheck = true;
                if (isRouteToExistingFile) {
                    // If we're not routing existing files and the file exists, we stop processing routes
                    return null;
                }
            }

            // Go through all the configured routes and find the first one that returns a match
            using (GetReadLock()) {
                foreach (RouteBase route in this) {
                    RouteData routeData = route.GetRouteData(httpContext);
                    if (routeData != null) {
                        // If we're not routing existing files on this route and the file exists, we also stop processing routes
                        if (!route.RouteExistingFiles) {
                            if (!doneRouteCheck) {
                                isRouteToExistingFile = IsRouteToExistingFile(httpContext);
                                doneRouteCheck = true;
                            }
                            if (isRouteToExistingFile) {
                                return null;
                            }
                        }
                        return routeData;
                    }
                }
            }

            return null;
        }

 

 

 

 

 RouteData routeData = route.GetRouteData(httpContext);

Route

 

  public override RouteData GetRouteData(HttpContextBase httpContext) {
            // Parse incoming URL (we trim off the first two chars since they're always "~/")
            string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;

            RouteValueDictionary values = _parsedRoute.Match(requestPath, Defaults);

            if (values == null) {
                // If we got back a null value set, that means the URL did not match
                return null;
            }

            RouteData routeData = new RouteData(this, RouteHandler);

            // Validate the values
            if (!ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest)) {
                return null;
            }

            // Copy the matched values
            foreach (var value in values) {
                routeData.Values.Add(value.Key, value.Value);
            }

            // Copy the DataTokens from the Route to the RouteData
            if (DataTokens != null) {
                foreach (var prop in DataTokens) {
                    routeData.DataTokens[prop.Key] = prop.Value;
                }
            }

            return routeData;
        }

 

Controller

 protected override void ExecuteCore()
    {
      this.PossiblyLoadTempData();
      try
      {
        string requiredString = this.RouteData.GetRequiredString("action");
        if (this.ActionInvoker.InvokeAction(this.ControllerContext, requiredString))
          return;
        this.HandleUnknownAction(requiredString);
      }
      finally
      {
        this.PossiblySaveTempData();
      }
    }

 

 

ControllerActionInvoker

 /// <summary>
    /// 使用指定的控制器上下文来调用指定操作。
    /// </summary>
    /// 
    /// <returns>
    /// 执行操作的结果。
    /// </returns>
    /// <param name="controllerContext">控制器上下文。</param><param name="actionName">要调用的操作的名称。</param><exception cref="T:System.ArgumentNullException"><paramref name="controllerContext"/> 参数为 null。</exception><exception cref="T:System.ArgumentException"><paramref name="actionName"/> 参数为 null 或为空。</exception><exception cref="T:System.Threading.ThreadAbortException">线程在此操作的调用期间已中止。</exception><exception cref="T:System.Exception">在此操作的调用期间出现未指定的错误。</exception>
    public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
    {
      if (controllerContext == null)
        throw new ArgumentNullException("controllerContext");
      if (string.IsNullOrEmpty(actionName))
        throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
      ControllerDescriptor controllerDescriptor = this.GetControllerDescriptor(controllerContext);
      ActionDescriptor action = this.FindAction(controllerContext, controllerDescriptor, actionName);
      if (action == null)
        return false;
      FilterInfo filters = this.GetFilters(controllerContext, action);
      try
      {
        AuthorizationContext authorizationContext = this.InvokeAuthorizationFilters(controllerContext, filters.AuthorizationFilters, action);
        if (authorizationContext.Result != null)
        {
          this.InvokeActionResult(controllerContext, authorizationContext.Result);
        }
        else
        {
          if (controllerContext.Controller.ValidateRequest)
            ControllerActionInvoker.ValidateRequest(controllerContext);
          IDictionary<string, object> parameterValues = this.GetParameterValues(controllerContext, action);
          ActionExecutedContext actionExecutedContext = this.InvokeActionMethodWithFilters(controllerContext, filters.ActionFilters, action, parameterValues);
          this.InvokeActionResultWithFilters(controllerContext, filters.ResultFilters, actionExecutedContext.Result);
        }
      }
      catch (ThreadAbortException ex)
      {
        throw;
      }
      catch (Exception ex)
      {
        ExceptionContext exceptionContext = this.InvokeExceptionFilters(controllerContext, filters.ExceptionFilters, ex);
        if (!exceptionContext.ExceptionHandled)
          throw;
        else
          this.InvokeActionResult(controllerContext, exceptionContext.Result);
      }
      return true;
    }

 

 

/// <summary>
  /// 创建一个实现 IHttpHandler 接口的对象并向该对象传递请求上下文。
  /// </summary>
  public class MvcRouteHandler : IRouteHandler
  {
    private IControllerFactory _controllerFactory;

    /// <summary>
    /// 初始化 <see cref="T:System.Web.Mvc.MvcRouteHandler"/> 类的新实例。
    /// </summary>
    public MvcRouteHandler()
    {
    }

    /// <summary>
    /// 使用指定的工厂控制器对象初始化 <see cref="T:System.Web.Mvc.MvcRouteHandler"/> 类的新实例。
    /// </summary>
    /// <param name="controllerFactory">控制器工厂。</param>
    public MvcRouteHandler(IControllerFactory controllerFactory)
    {
      this._controllerFactory = controllerFactory;
    }

    /// <summary>
    /// 使用指定的 HTTP 上下文返回 HTTP 处理程序。
    /// </summary>
    /// 
    /// <returns>
    /// HTTP 处理程序。
    /// </returns>
    /// <param name="requestContext">请求上下文。</param>
    protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
      requestContext.HttpContext.SetSessionStateBehavior(this.GetSessionStateBehavior(requestContext));
      return (IHttpHandler) new MvcHandler(requestContext);
    }

 

posted @ 2015-11-30 14:05  awp110  阅读(462)  评论(0编辑  收藏  举报