软件下载 | 资讯教程 | 最近更新 | 下载排行 | 一键转帖 | 发布投稿
您的位置:最火下载站 > 网络编程 > ASP.NET > ASP.NET MVC 1.0 流程分析(ControllerActionInvoker)

ASP.NET MVC 1.0 流程分析(ControllerActionInvoker)

ControllerActionInvoker 类型的代码还是值得称赞的,核心调用代码简单明了,相关分解方法清晰干净,让人很容易理解这个复杂的执行过程。

public class ControllerActionInvoker : IActionInvoker
{
public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
{
...

ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
ActionDescriptor actionDescriptor = FindAction(controllerContext, controllerDescriptor,
actionName);

if (actionDescriptor != null)
{
FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);

try
{
AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext,
filterInfo.AuthorizationFilters, actionDescriptor);

if (authContext.Result != null)
{
// the auth filter signaled that we should let it short-circuit the request
InvokeActionResult(controllerContext, authContext.Result);
}
else
{
if (controllerContext.Controller.ValidateRequest)
{
ValidateRequest(controllerContext.HttpContext.Request);
}

IDictionary<string, object> parameters = GetParameterValues(controllerContext,
actionDescriptor);

ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(
controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);

InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters,
postActionContext.Result);
}
}
catch (ThreadAbortException)
{
// This type of exception occurs as a result of Response.Redirect(), but we special-case
// so that the filters don't see this as an error.
throw;
}
catch (Exception ex)
{
// something blew up, so execute the exception filters
ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext,
filterInfo.ExceptionFilters, ex);

if (!exceptionContext.ExceptionHandled)
{
throw;
}

InvokeActionResult(controllerContext, exceptionContext.Result);
}

return true;
}

// notify controller that no method matched
return false;
}
}

1. GetControllerDescriptor: 首先获取 ControllerDescriptor,实际默认返回的是 ReflectedControllerDescriptor。

public class ControllerActionInvoker : IActionInvoker
{
protected virtual ControllerDescriptor GetControllerDescriptor(ControllerContext controllerContext)
{
Type controllerType = controllerContext.Controller.GetType();
ControllerDescriptor controllerDescriptor = DescriptorCache.GetDescriptor(controllerType);
return controllerDescriptor;
}

private readonly static ControllerDescriptorCache _staticDescriptorCache = new ControllerDescriptorCache();

internal ControllerDescriptorCache DescriptorCache
{
get
{
if (_instanceDescriptorCache == null)
{
_instanceDescriptorCache = _staticDescriptorCache;
}
return _instanceDescriptorCache;
}
...
}
}

internal sealed class ControllerDescriptorCache : ReaderWriterCache<Type, ControllerDescriptor>
{
public ControllerDescriptor GetDescriptor(Type controllerType)
{
return FetchOrCreateItem(controllerType, () => new ReflectedControllerDescriptor(controllerType));
}
}

2. FindAction: 查找实际的执行 Action 信息,返回 ReflectedActionDescriptor。

public class ControllerActionInvoker : IActionInvoker
{
protected virtual ActionDescriptor FindAction(ControllerContext controllerContext, ...)
{
ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
return actionDescriptor;
}
}

public class ReflectedControllerDescriptor : ControllerDescriptor
{
public ReflectedControllerDescriptor(Type controllerType)
{
...
_selector = new ActionMethodSelector(_controllerType);
}

public override ActionDescriptor FindAction(ControllerContext controllerContext, string actionName)
{
...

MethodInfo matched = _selector.FindActionMethod(controllerContext, actionName);
if (matched == null)
{
return null;
}

return new ReflectedActionDescriptor(matched, actionName, this);
}
}

继续往里走,看看 _selector.FindActionMethod() 如何返回实际的 Action MethodInfo。

internal sealed class ActionMethodSelector
{
public MethodInfo FindActionMethod(ControllerContext controllerContext, string actionName)
{
List<MethodInfo> methodsMatchingName = GetMatchingAliasedMethods(controllerContext, actionName);
methodsMatchingName.AddRange(NonAliasedMethods[actionName]);
List<MethodInfo> finalMethods = RunSelectionFilters(controllerContext, methodsMatchingName);

switch (finalMethods.Count)
{
case 0:
return null;
case 1:
return finalMethods[0];
default:
throw CreateAmbiguousMatchException(finalMethods, actionName);
}
}
}

相关阅读
栏目导航
推荐软件