• 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 + " " + 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 + " "); // 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);
        }
  • 相关阅读:
    CentOS 7 下Django项目部署(基于uwsgi和Nginx)
    群晖 利用docker和同步远程修改服务配置
    Fody 很方便,也有不方便的时候
    HTTP请求中Get、Post与后台参数接收的分析
    微信小程序跨页面跨组件通讯eventbus
    import、require、export、module.exports 混合使用详解
    JavaScript中Object对象方法总结
    关于存储过程调用视图的效率问题
    思想的痕迹
    Gmail、Orkut和Wallop的不限量,不限时邀请
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/5006994.html
Copyright © 2020-2023  润新知