MVC控制器执行


通过前篇我们了解了MVC路由解析及控制器创建。

得到控制器之后就是执行了

// System.Web.Mvc.IController
/// Executes the specified request context.
/// The request context.
void Execute(RequestContext requestContext);

IController的接口,就一个方法Execute的方法,参数为RequestConext

graph LR
IController-->ControllerBase
ControllerBase-->Controller

以上是Controller的继承关系

IContrller接口的Execute被ControllerBase实现

// System.Web.Mvc.ControllerBase
/// Executes the specified request context.
/// The request context.
/// The  parameter is null.
protected virtual void Execute(RequestContext requestContext)
{
	if (requestContext == null)
	{
		throw new ArgumentNullException("requestContext");
	}
	if (requestContext.HttpContext == null)
	{
		throw new ArgumentException(MvcResources.ControllerBase_CannotExecuteWithNullHttpContext, "requestContext");
	}
	this.VerifyExecuteCalledOnce();
	this.Initialize(requestContext);
	using (ScopeStorage.CreateTransientScope())
	{
		this.ExecuteCore();
	}
}
// System.Web.Mvc.ControllerBase
/// Initializes the specified request context.
/// The request context.
protected virtual void Initialize(RequestContext requestContext)
{
	this.ControllerContext = new ControllerContext(requestContext, this);
}
// System.Web.Mvc.Controller
/// Initializes data that might not be available when the constructor is called.
/// The HTTP context and route data.
protected override void Initialize(RequestContext requestContext)
{
	base.Initialize(requestContext);
	this.Url = new UrlHelper(requestContext);
}

Execute方法,VerifyExecuteCalledOnce()看方法名的意思应该是验证是否是第一次执行,Initialize()就是将请求的上下文和Controller做个了绑定,ScopeStorage.CreateTransientScope()然后using了一个作用域,最后交给子类的ExecuteCore方法

// System.Web.Mvc.Controller
/// Invokes the action in the current controller context.
protected override void ExecuteCore()
{
	this.PossiblyLoadTempData();
	try
	{
		string actionName = Controller.GetActionName(this.RouteData);
		if (!this.ActionInvoker.InvokeAction(base.ControllerContext, actionName))
		{
			this.HandleUnknownAction(actionName);
		}
	}
	finally
	{
		this.PossiblySaveTempData();
	}
}

PossiblyLoadTempData()看方法名就知道是加载TempData,PossiblySaveTempData()是保存TempData

// System.Web.Mvc.Controller
internal void PossiblyLoadTempData()
{
	if (!base.ControllerContext.IsChildAction)
	{
		base.TempData.Load(base.ControllerContext, this.TempDataProvider);
	}
}
// System.Web.Mvc.TempDataDictionary
/// Loads the specified controller context by using the specified data provider.
/// The controller context.
/// The temporary data provider.
public void Load(ControllerContext controllerContext, ITempDataProvider tempDataProvider)
{
	IDictionary dictionary = tempDataProvider.LoadTempData(controllerContext);
	this._data = ((dictionary != null) ? new Dictionary(dictionary, StringComparer.OrdinalIgnoreCase) : new Dictionary(StringComparer.OrdinalIgnoreCase));
	this._initialKeys = new HashSet(this._data.Keys, StringComparer.OrdinalIgnoreCase);
	this._retainedKeys.Clear();
}
// System.Web.Mvc.SessionStateTempDataProvider
/// Loads the temporary data by using the specified controller context.
/// The temporary data.
/// The controller context.
/// An error occurred when the session context was being retrieved.
public virtual IDictionary LoadTempData(ControllerContext controllerContext)
{
	HttpSessionStateBase session = controllerContext.HttpContext.Session;
	if (session != null)
	{
		Dictionary dictionary = session["__ControllerTempData"] as Dictionary;
		if (dictionary != null)
		{
			session.Remove("__ControllerTempData");
			return dictionary;
		}
	}
	return new Dictionary(StringComparer.OrdinalIgnoreCase);
}
// System.Web.Mvc.Controller
internal void PossiblySaveTempData()
{
	if (!base.ControllerContext.IsChildAction)
	{
		base.TempData.Save(base.ControllerContext, this.TempDataProvider);
	}
}
// System.Web.Mvc.TempDataDictionary
/// Saves the specified controller context by using the specified data provider.
/// The controller context.
/// The temporary data provider.
public void Save(ControllerContext controllerContext, ITempDataProvider tempDataProvider)
{
	this._data.RemoveFromDictionary(delegate(KeyValuePair entry, TempDataDictionary tempData)
	{
		string key = entry.Key;
		return !tempData._initialKeys.Contains(key) && !tempData._retainedKeys.Contains(key);
	}
	, this);
	tempDataProvider.SaveTempData(controllerContext, this._data);
}
// System.Web.Mvc.SessionStateTempDataProvider
/// Saves the specified values in the temporary data dictionary by using the specified controller context.
/// The controller context.
/// The values.
/// An error occurred the session context was being retrieved.
public virtual void SaveTempData(ControllerContext controllerContext, IDictionary values)
{
	if (controllerContext == null)
	{
		throw new ArgumentNullException("controllerContext");
	}
	HttpSessionStateBase session = controllerContext.HttpContext.Session;
	bool flag = values != null && values.Count > 0;
	if (session == null)
	{
		if (flag)
		{
			throw new InvalidOperationException(MvcResources.SessionStateTempDataProvider_SessionStateDisabled);
		}
	}
	else
	{
		if (flag)
		{
			session["__ControllerTempData"] = values;
			return;
		}
		if (session["__ControllerTempData"] != null)
		{
			session.Remove("__ControllerTempData");
		}
	}
}

回到Controller ExecuteCore()方法中

string actionName = Controller.GetActionName(this.RouteData);

通过路由获取actionName,调用ActionInvoker.InvokeAction如果返回false,就抛出异常

// System.Web.Mvc.Controller
/// Gets the action invoker for the controller.
/// The action invoker.
public IActionInvoker ActionInvoker
{
	get
	{
		if (this._actionInvoker == null)
		{
			this._actionInvoker = this.CreateActionInvoker();
		}
		return this._actionInvoker;
	}
	set
	{
		this._actionInvoker = value;
	}
}
// System.Web.Mvc.Controller
/// Creates an action invoker.
/// An action invoker.
protected virtual IActionInvoker CreateActionInvoker()
{
	IAsyncActionInvokerFactory service = this.Resolver.GetService();
	if (service != null)
	{
		return service.CreateInstance();
	}
	IActionInvokerFactory service2 = this.Resolver.GetService();
	if (service2 != null)
	{
		return service2.CreateInstance();
	}
	IAsyncActionInvoker arg_4F_0;
	if ((arg_4F_0 = this.Resolver.GetService()) == null)
	{
		arg_4F_0 = (this.Resolver.GetService() ?? new AsyncControllerActionInvoker());
	}
	return arg_4F_0;
}

ActionInvoker默认取异步IAsyncActionInvoker,没有则取IActionInvoker,最终InvokeAction是在ControllerActionInvoker里面实现的

// System.Web.Mvc.ControllerActionInvoker
/// Invokes the specified action by using the specified controller context.
/// The result of executing the action.
/// The controller context.
/// The name of the action to invoke.
/// The  parameter is null.
/// The  parameter is null or empty.
/// The thread was aborted during invocation of the action.
/// An unspecified error occurred during invocation of the action.
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
{
	if (controllerContext == null)
	{
		throw new ArgumentNullException("controllerContext");
	}
	if (string.IsNullOrEmpty(actionName) && !controllerContext.RouteData.HasDirectRouteMatch())
	{
		throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
	}
	ControllerDescriptor controllerDescriptor = this.GetControllerDescriptor(controllerContext);
	ActionDescriptor actionDescriptor = this.FindAction(controllerContext, controllerDescriptor, actionName);
	if (actionDescriptor != null)
	{
		FilterInfo filters = this.GetFilters(controllerContext, actionDescriptor);
		try
		{
			AuthenticationContext authenticationContext = this.InvokeAuthenticationFilters(controllerContext, filters.AuthenticationFilters, actionDescriptor);
			if (authenticationContext.Result != null)
			{
				AuthenticationChallengeContext authenticationChallengeContext = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, actionDescriptor, authenticationContext.Result);
				this.InvokeActionResult(controllerContext, authenticationChallengeContext.Result ?? authenticationContext.Result);
			}
			else
			{
				AuthorizationContext authorizationContext = this.InvokeAuthorizationFilters(controllerContext, filters.AuthorizationFilters, actionDescriptor);
				if (authorizationContext.Result != null)
				{
					AuthenticationChallengeContext authenticationChallengeContext2 = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, actionDescriptor, authorizationContext.Result);
					this.InvokeActionResult(controllerContext, authenticationChallengeContext2.Result ?? authorizationContext.Result);
				}
				else
				{
					if (controllerContext.Controller.ValidateRequest)
					{
						ControllerActionInvoker.ValidateRequest(controllerContext);
					}
					IDictionary parameterValues = this.GetParameterValues(controllerContext, actionDescriptor);
					ActionExecutedContext actionExecutedContext = this.InvokeActionMethodWithFilters(controllerContext, filters.ActionFilters, actionDescriptor, parameterValues);
					AuthenticationChallengeContext authenticationChallengeContext3 = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, actionDescriptor, actionExecutedContext.Result);
					this.InvokeActionResultWithFilters(controllerContext, filters.ResultFilters, authenticationChallengeContext3.Result ?? actionExecutedContext.Result);
				}
			}
		}
		catch (ThreadAbortException)
		{
			throw;
		}
		catch (Exception exception)
		{
			ExceptionContext exceptionContext = this.InvokeExceptionFilters(controllerContext, filters.ExceptionFilters, exception);
			if (!exceptionContext.ExceptionHandled)
			{
				throw;
			}
			this.InvokeActionResult(controllerContext, exceptionContext.Result);
		}
		return true;
	}
	return false;
}

ControllerActionInvoker.InvokeAction()先获得了两个Descriptor

// System.Web.Mvc.ControllerActionInvoker
/// Retrieves information about the controller by using the specified controller context.
/// Information about the controller.
/// The controller context.
protected virtual ControllerDescriptor GetControllerDescriptor(ControllerContext controllerContext)
{
	Type type = controllerContext.Controller.GetType();
	return this.DescriptorCache.GetDescriptor(type, (Type innerType) => new ReflectedControllerDescriptor(innerType), type);
}
// System.Web.Mvc.ControllerActionInvoker
/// Finds the information about the action method.
/// Information about the action method.
/// The controller context.
/// The controller descriptor.
/// The name of the action.
protected virtual ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)
{
	if (!controllerContext.RouteData.HasDirectRouteMatch())
	{
		return controllerDescriptor.FindAction(controllerContext, actionName);
	}
	List directRouteCandidates = ControllerActionInvoker.GetDirectRouteCandidates(controllerContext);
	DirectRouteCandidate directRouteCandidate = DirectRouteCandidate.SelectBestCandidate(directRouteCandidates, controllerContext);
	if (directRouteCandidate == null)
	{
		return null;
	}
	controllerContext.RouteData = directRouteCandidate.RouteData;
	controllerContext.RequestContext.RouteData = directRouteCandidate.RouteData;
	directRouteCandidate.RouteData.Values.RemoveFromDictionary((KeyValuePair entry) => entry.Value == UrlParameter.Optional);
	return directRouteCandidate.ActionDescriptor;
}

首先获得Controller的Type,然后从DescriptorCache(缓存)获取ControllerDescriptor。如果没有的话 就使用ReflectedControllerDescriptor

// System.Web.Mvc.ControllerActionInvoker
/// Finds the information about the action method.
/// Information about the action method.
/// The controller context.
/// The controller descriptor.
/// The name of the action.
protected virtual ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)
{
	if (!controllerContext.RouteData.HasDirectRouteMatch())
	{
		return controllerDescriptor.FindAction(controllerContext, actionName);
	}
	List directRouteCandidates = ControllerActionInvoker.GetDirectRouteCandidates(controllerContext);
	DirectRouteCandidate directRouteCandidate = DirectRouteCandidate.SelectBestCandidate(directRouteCandidates, controllerContext);
	if (directRouteCandidate == null)
	{
		return null;
	}
	controllerContext.RouteData = directRouteCandidate.RouteData;
	controllerContext.RequestContext.RouteData = directRouteCandidate.RouteData;
	directRouteCandidate.RouteData.Values.RemoveFromDictionary((KeyValuePair entry) => entry.Value == UrlParameter.Optional);
	return directRouteCandidate.ActionDescriptor;
}
// System.Web.Mvc.Routing.DirectRouteExtensions
public static bool HasDirectRouteMatch(this RouteData routeData)
{
	if (routeData == null)
	{
		throw Error.ArgumentNull("routeData");
	}
	return routeData.Values.ContainsKey("MS_DirectRouteMatches");
}
// System.Web.Mvc.ReflectedControllerDescriptor
/// Finds the specified action for the specified controller context.
/// The information about the action.
/// The controller context.
/// The name of the action.
/// The  parameter is null.
/// The  parameter is null or empty.
public override ActionDescriptor FindAction(ControllerContext controllerContext, string actionName)
{
	if (controllerContext == null)
	{
		throw new ArgumentNullException("controllerContext");
	}
	if (string.IsNullOrEmpty(actionName))
	{
		throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
	}
	MethodInfo methodInfo = this._selector.FindActionMethod(controllerContext, actionName);
	if (methodInfo == null)
	{
		return null;
	}
	return new ReflectedActionDescriptor(methodInfo, actionName, this);
}

接下来是获取ActionDescriptor,先检查路由是否有MS_DirectRouteMatches,没有则返回控制器中的ActionDescriptor没有就提供一个ReflectedActionDescriptor,有则从路由中取

// System.Web.Mvc.ControllerActionInvoker
private static List GetDirectRouteCandidates(ControllerContext controllerContext)
{
	List list = new List();
	RouteData routeData = controllerContext.RouteData;
	foreach (RouteData current in routeData.GetDirectRouteMatches())
	{
		if (current != null)
		{
			if (current.GetTargetControllerDescriptor() == null)
			{
				throw new InvalidOperationException(MvcResources.DirectRoute_MissingControllerDescriptor);
			}
			ActionDescriptor[] targetActionDescriptors = current.GetTargetActionDescriptors();
			if (targetActionDescriptors == null || targetActionDescriptors.Length == 0)
			{
				throw new InvalidOperationException(MvcResources.DirectRoute_MissingActionDescriptors);
			}
			ActionDescriptor[] array = targetActionDescriptors;
			for (int i = 0; i < array.Length; i++)
			{
				ActionDescriptor actionDescriptor = array[i];
				if (actionDescriptor != null)
				{
					list.Add(new DirectRouteCandidate
					{
						ActionDescriptor = actionDescriptor, 
						ActionNameSelectors = actionDescriptor.GetNameSelectors(), 
						ActionSelectors = actionDescriptor.GetSelectors(), 
						Order = current.GetOrder(), 
						Precedence = current.GetPrecedence(), 
						RouteData = current
					});
				}
			}
		}
	}
	return list;
}
// System.Web.Mvc.Routing.DirectRouteExtensions
public static ActionDescriptor[] GetTargetActionDescriptors(this RouteData routeData)
{
	return routeData.GetRouteDataTokenValue("MS_DirectRouteActions");
}

回到ControllerActionInvoker.InvokeAction()中,获取两个Descriptor之后,获取FilterInfo

FilterInfo filters = this.GetFilters(controllerContext, actionDescriptor);
// System.Web.Mvc.ControllerActionInvoker
/// Retrieves information about the action filters.
/// Information about the action filters.
/// The controller context.
/// The action descriptor.
protected virtual FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
	return new FilterInfo(this._getFiltersThunk(controllerContext, actionDescriptor));
}
// System.Web.Mvc.ControllerActionInvoker
private Func> _getFiltersThunk = new Func>(FilterProviders.Providers.GetFilters);

using System;
namespace System.Web.Mvc
{
	/// Provides a registration point for filters.
	public static class FilterProviders
	{
		/// Provides a registration point for filters.
		/// The collection of filters.
		public static FilterProviderCollection Providers
		{
			get;
			private set;
		}
		static FilterProviders()
		{
			FilterProviders.Providers = new FilterProviderCollection();
			FilterProviders.Providers.Add(GlobalFilters.Filters);
			FilterProviders.Providers.Add(new FilterAttributeFilterProvider());
			FilterProviders.Providers.Add(new ControllerInstanceFilterProvider());
		}
	}
}

实例化FilterInfo需要注册Filter,在静态类FilterProviders中分别对Global、FilterAttribute、ControllerInstance的Filter注册,然后对Filter分类整理

/// Initializes a new instance of the  class using the specified filters collection.
/// The filters collection.
public FilterInfo(IEnumerable filters)
{
	FilterInfo.OverrideFilterInfo info = FilterInfo.ProcessOverrideFilters(filters);
	this.SplitFilters(info);
}
// System.Web.Mvc.FilterInfo
private static FilterInfo.OverrideFilterInfo ProcessOverrideFilters(IEnumerable filters)
{
	FilterInfo.OverrideFilterInfo result = new FilterInfo.OverrideFilterInfo
	{
		ActionOverrideScope = FilterScope.First, 
		AuthenticationOverrideScope = FilterScope.First, 
		AuthorizationOverrideScope = FilterScope.First, 
		ExceptionOverrideScope = FilterScope.First, 
		ResultOverrideScope = FilterScope.First, 
		Filters = new List()
	};
	foreach (Filter current in filters)
	{
		if (current != null)
		{
			IOverrideFilter overrideFilter = current.Instance as IOverrideFilter;
			if (overrideFilter != null)
			{
				if (overrideFilter.FiltersToOverride == typeof(IActionFilter) && current.Scope >= result.ActionOverrideScope)
				{
					result.ActionOverrideScope = current.Scope;
				}
				else
				{
					if (overrideFilter.FiltersToOverride == typeof(IAuthenticationFilter) && current.Scope >= result.AuthenticationOverrideScope)
					{
						result.AuthenticationOverrideScope = current.Scope;
					}
					else
					{
						if (overrideFilter.FiltersToOverride == typeof(IAuthorizationFilter) && current.Scope >= result.AuthorizationOverrideScope)
						{
							result.AuthorizationOverrideScope = current.Scope;
						}
						else
						{
							if (overrideFilter.FiltersToOverride == typeof(IExceptionFilter) && current.Scope >= result.ExceptionOverrideScope)
							{
								result.ExceptionOverrideScope = current.Scope;
							}
							else
							{
								if (overrideFilter.FiltersToOverride == typeof(IResultFilter) && current.Scope >= result.ResultOverrideScope)
								{
									result.ResultOverrideScope = current.Scope;
								}
							}
						}
					}
				}
			}
			result.Filters.Add(current);
		}
	}
	return result;
}
// System.Web.Mvc.FilterInfo
private void SplitFilters(FilterInfo.OverrideFilterInfo info)
{
	foreach (Filter current in info.Filters)
	{
		IActionFilter actionFilter = current.Instance as IActionFilter;
		if (actionFilter != null && current.Scope >= info.ActionOverrideScope)
		{
			this._actionFilters.Add(actionFilter);
		}
		IAuthenticationFilter authenticationFilter = current.Instance as IAuthenticationFilter;
		if (authenticationFilter != null && current.Scope >= info.AuthenticationOverrideScope)
		{
			this._authenticationFilters.Add(authenticationFilter);
		}
		IAuthorizationFilter authorizationFilter = current.Instance as IAuthorizationFilter;
		if (authorizationFilter != null && current.Scope >= info.AuthorizationOverrideScope)
		{
			this._authorizationFilters.Add(authorizationFilter);
		}
		IExceptionFilter exceptionFilter = current.Instance as IExceptionFilter;
		if (exceptionFilter != null && current.Scope >= info.ExceptionOverrideScope)
		{
			this._exceptionFilters.Add(exceptionFilter);
		}
		IResultFilter resultFilter = current.Instance as IResultFilter;
		if (resultFilter != null && current.Scope >= info.ResultOverrideScope)
		{
			this._resultFilters.Add(resultFilter);
		}
	}
}

回到ControllerActionInvoker.InvokeAction()继续执行InvokeAuthenticationFilters

// System.Web.Mvc.ControllerActionInvoker
protected virtual AuthenticationContext InvokeAuthenticationFilters(ControllerContext controllerContext, IList filters, ActionDescriptor actionDescriptor)
{
	if (controllerContext == null)
	{
		throw new ArgumentNullException("controllerContext");
	}
	IPrincipal user = controllerContext.HttpContext.User;
	AuthenticationContext authenticationContext = new AuthenticationContext(controllerContext, actionDescriptor, user);
	foreach (IAuthenticationFilter current in filters)
	{
		current.OnAuthentication(authenticationContext);
		if (authenticationContext.Result != null)
		{
			break;
		}
	}
	IPrincipal principal = authenticationContext.Principal;
	if (principal != user)
	{
		authenticationContext.HttpContext.User = principal;
		Thread.CurrentPrincipal = principal;
	}
	return authenticationContext;
}
// System.Web.Mvc.Filters.IAuthenticationFilter
/// Authenticates the request.
/// The context to use for authentication.
void OnAuthentication(AuthenticationContext filterContext);

执行所有注册的IAuthenticationFilter.OnAuthentication()方法,如果返回有Result则跳出循环,执行ControllerActionInvoker.InvokeAuthenticationFiltersChallenge()并执行所有注册的IAuthenticationFilter.OnAuthenticationChallenge()方法,最后执行ControllerActionInvoker.InvokeActionResult()

// System.Web.Mvc.ControllerActionInvoker
protected virtual AuthenticationChallengeContext InvokeAuthenticationFiltersChallenge(ControllerContext controllerContext, IList filters, ActionDescriptor actionDescriptor, ActionResult result)
{
	AuthenticationChallengeContext authenticationChallengeContext = new AuthenticationChallengeContext(controllerContext, actionDescriptor, result);
	foreach (IAuthenticationFilter current in filters)
	{
		current.OnAuthenticationChallenge(authenticationChallengeContext);
	}
	return authenticationChallengeContext;
}
// System.Web.Mvc.Filters.IAuthenticationFilter
/// Adds an authentication challenge to the current .
/// The context to use for the authentication challenge.
void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext);
// System.Web.Mvc.ControllerActionInvoker
/// Invokes the specified action result by using the specified controller context.
/// The controller context.
/// The action result.
protected virtual void InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
{
	actionResult.ExecuteResult(controllerContext);
}

没有返回Result,继续执行ControllerActionInvoker.InvokeAuthorizationFilters

// System.Web.Mvc.ControllerActionInvoker
/// Invokes the specified authorization filters by using the specified action descriptor and controller context.
/// The context for the  object.
/// The controller context.
/// The authorization filters.
/// The action descriptor.
protected virtual AuthorizationContext InvokeAuthorizationFilters(ControllerContext controllerContext, IList filters, ActionDescriptor actionDescriptor)
{
	AuthorizationContext authorizationContext = new AuthorizationContext(controllerContext, actionDescriptor);
	foreach (IAuthorizationFilter current in filters)
	{
		current.OnAuthorization(authorizationContext);
		if (authorizationContext.Result != null)
		{
			break;
		}
	}
	return authorizationContext;
}
// System.Web.Mvc.IAuthorizationFilter
/// Called when authorization is required.
/// The filter context.
void OnAuthorization(AuthorizationContext filterContext);

和前面同理,一个是身份验证,一个是检测是否授权

下一步ValidateRequest,验证请求

if (controllerContext.Controller.ValidateRequest)
{
     ControllerActionInvoker.ValidateRequest(controllerContext);
}
// System.Web.Mvc.ControllerActionInvoker
internal static void ValidateRequest(ControllerContext controllerContext)
{
	if (controllerContext.IsChildAction)
	{
		return;
	}
	HttpContext current = HttpContext.Current;
	if (current != null)
	{
		ValidationUtility.EnableDynamicValidation(current);
	}
	controllerContext.HttpContext.Request.ValidateInput();
}

ControllerBase默认设置需要验证请求

// System.Web.Mvc.ControllerBase
/// Gets or sets a value that indicates whether request validation is enabled for this request.
/// true if request validation is enabled for this request; otherwise, false. The default is true.
public bool ValidateRequest
{
	get
	{
		return this._validateRequest;
	}
	set
	{
		this._validateRequest = value;
	}
}
private bool _validateRequest = true;

下一步 绑定Action参数

IDictionary parameterValues = this.GetParameterValues(controllerContext, actionDescriptor);

下一步 带ActionFilters并执行方法

ActionExecutedContext actionExecutedContext = this.InvokeActionMethodWithFilters(controllerContext, filters.ActionFilters, actionDescriptor, parameterValues);
// System.Web.Mvc.ControllerActionInvoker
/// Invokes the specified action method by using the specified parameters, controller context, and action filters.
/// The context for the ActionExecuted method of the  class.
/// The controller context.
/// The action filters.
/// The action descriptor.
/// The parameters.
protected virtual ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList filters, ActionDescriptor actionDescriptor, IDictionary parameters)
{
	ActionExecutingContext preContext = new ActionExecutingContext(controllerContext, actionDescriptor, parameters);
	Func seed = () => new ActionExecutedContext(controllerContext, actionDescriptor, false, null)
	{
		Result = this.InvokeActionMethod(controllerContext, actionDescriptor, parameters)
	};
	Func func = filters.Reverse().Aggregate(seed, (Func next, IActionFilter filter) => () => ControllerActionInvoker.InvokeActionMethodFilter(filter, preContext, next));
	return func();
}
// System.Web.Mvc.ControllerActionInvoker
/// Invokes the specified action method by using the specified parameters and the controller context.
/// The result of executing the action method.
/// The controller context.
/// The action descriptor.
/// The parameters.
protected virtual ActionResult InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary parameters)
{
	object actionReturnValue = actionDescriptor.Execute(controllerContext, parameters);
	return this.CreateActionResult(controllerContext, actionDescriptor, actionReturnValue);
}
// System.Linq.Enumerable
[__DynamicallyInvokable]
public static TAccumulate Aggregate(this IEnumerable source, TAccumulate seed, Func func)
{
	if (source == null)
	{
		throw Error.ArgumentNull("source");
	}
	if (func == null)
	{
		throw Error.ArgumentNull("func");
	}
	TAccumulate tAccumulate = seed;
	foreach (TSource current in source)
	{
		tAccumulate = func(tAccumulate, current);
	}
	return tAccumulate;
}
// System.Web.Mvc.ControllerActionInvoker
internal static ActionExecutedContext InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func continuation)
{
	filter.OnActionExecuting(preContext);
	if (preContext.Result != null)
	{
		return new ActionExecutedContext(preContext, preContext.ActionDescriptor, true, null)
		{
			Result = preContext.Result
		};
	}
	bool flag = false;
	ActionExecutedContext actionExecutedContext = null;
	try
	{
		actionExecutedContext = continuation();
	}
	catch (ThreadAbortException)
	{
		actionExecutedContext = new ActionExecutedContext(preContext, preContext.ActionDescriptor, false, null);
		filter.OnActionExecuted(actionExecutedContext);
		throw;
	}
	catch (Exception exception)
	{
		flag = true;
		actionExecutedContext = new ActionExecutedContext(preContext, preContext.ActionDescriptor, false, exception);
		filter.OnActionExecuted(actionExecutedContext);
		if (!actionExecutedContext.ExceptionHandled)
		{
			throw;
		}
	}
	if (!flag)
	{
		filter.OnActionExecuted(actionExecutedContext);
	}
	return actionExecutedContext;
}

这里Filter执行流程类似于俄罗斯套娃

graph TD
A(ActionFilter_1.OnActionExecuting)-->B(ActionFilter_2.OnActionExecuting)
B-->|... ...|C(ActionFilter_n.OnActionExecuting)
C-->D(InvokeActionMethod)
D-->E(ActionFilter_n.OnActionExecuted)
E-->|... ...|F(ActionFilter_2.OnActionExecuted)
F-->G(ActionFilter_1.OnActionExecuted)

本文参考文档: