MVC ASP.net流程 源代码分析

时间:2021-02-26 14:34:27

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[] == '.') {
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 ;
}
else {
// need to restart app domain
HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged,
SR.GetString(SR.Hosting_Phys_Path_Changed,
adPath,
wrPath));
return ;
}
}
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 ;
} // 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(, "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(, "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 > ) {
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(); // 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 >= , "_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 = ; i < handlers.Length; i++) {
MethodInfo appMethod = handlers[i];
String appMethodName = appMethod.Name;
int namePosIndex = appMethodName.IndexOf('_');
String targetName = appMethodName.Substring(, 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+); EventDescriptor foundEvent = events.Find(eventName, true);
if (foundEvent == null
&& StringUtil.EqualsIgnoreCase(eventName.Substring(, ), "on")) { eventName = eventName.Substring();
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 != )
continue; // Create the delegate from app method to pass to AddXXX(handler) method Delegate handlerDelegate = null; ParameterInfo[] appMethodParams = appMethod.GetParameters(); if (appMethodParams.Length == ) {
// If the app method doesn't have arguments --
// -- hookup via intermidiate handler // only can do it for EventHandler, not strongly typed
if (addMethodParams[].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[].ParameterType, this, appMethodName);
}
catch {
// some type mismatch
continue;
}
} // Call the AddXXX() to hook up the delegate try {
addMethod.Invoke(target, new Object[]{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(, 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 == ) {
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() + 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);
}