码迷,mamicode.com
首页 > Web开发 > 详细

MVC 请求处理流程(二)

时间:2015-03-13 10:42:31      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:

[上一篇]中我们说到了对象AsyncControllerActionInvoker,在Controller的ExecuteCore方法中调用AsyncControllerActionInvoker对象的InvokeAction方法来执行动作方法.

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;
}

这个方法是在AsyncControllerActionInvoker的基类ControllerActionInvoker中实现的,而且做了很做工作,我们来逐步分解这个方法,首先,获取控制器的描述对象方法

protected virtual ControllerDescriptor GetControllerDescriptor(ControllerContext controllerContext)
{
      Type controllerType = controllerContext.Controller.GetType();
      return this.DescriptorCache.GetDescriptor(controllerType, (Func<ControllerDescriptor>) (() => (ControllerDescriptor) new ReflectedControllerDescriptor(controllerType)));
}

在这个方法中,获取Controller描述对象默认为ReflectedControllerDescriptor。然后再根据动作方法名称获取动作描述对象ActionDescriptor,

protected virtual ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)
{
      return controllerDescriptor.FindAction(controllerContext, actionName);
}

可以看到其实调用的是控制器描述对象的获取动作描述对象的方法,我们根据获取的默认控制器描述对象ReflectedControllerDescriptor,查看它的FindAction:

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 actionMethod = this._selector.FindActionMethod(controllerContext, actionName);
      if (actionMethod == (MethodInfo) null)
        return (ActionDescriptor) null;
      else
        return (ActionDescriptor) new ReflectedActionDescriptor(actionMethod, actionName, (ControllerDescriptor) this);
}

返回默认是封装了要调用的方法对象 MethodInfo的ReflectedActionDescriptor对象。

  下来一步是根据控制器上下文和动作描述对象获取到应用到动作和控制器上的所有筛选器,并从获取到的所有筛选器中得到授权过滤器,然后对每个授权过滤器调用OnAuthorization方法,判断返回的AuthorizationContext的Result如果不为空,就直接调用动作结果方法InvokeActionResult。如果为空,说明授权都通过了,然后获取动作方法的参数和根据模型绑定器绑定参数值,(这里会涉及到另外一个组件IModelBinder,我们会在后续详细谈论它,在这里我们就只需知道他会根据参数名称从请求的数据中绑定参数值)

protected virtual IDictionary<string, object> GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
      Dictionary<string, object> dictionary = new Dictionary<string, object>((IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase);
      foreach (ParameterDescriptor parameterDescriptor in actionDescriptor.GetParameters())
        dictionary[parameterDescriptor.ParameterName] = this.GetParameterValue(controllerContext, parameterDescriptor);
      return (IDictionary<string, object>) dictionary;
}

 

protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
{
      Type parameterType = parameterDescriptor.ParameterType;
      IModelBinder modelBinder = this.GetModelBinder(parameterDescriptor);
      IValueProvider valueProvider = controllerContext.Controller.ValueProvider;
      string str = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;
      Predicate<string> propertyFilter = ControllerActionInvoker.GetPropertyFilter(parameterDescriptor);
      ModelBindingContext bindingContext = new ModelBindingContext()
      {
        FallbackToEmptyPrefix = parameterDescriptor.BindingInfo.Prefix == null,
        ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType((Func<object>) null, parameterType),
        ModelName = str,
        ModelState = controllerContext.Controller.ViewData.ModelState,
        PropertyFilter = propertyFilter,
        ValueProvider = valueProvider
      };
      return modelBinder.BindModel(controllerContext, bindingContext) ?? parameterDescriptor.DefaultValue;
}

再下来根据控制器描述对象,动作描述对象和或取得的参数执行InvokeActionMethod方法:

protected virtual ActionResult InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
 {
      object actionReturnValue = actionDescriptor.Execute(controllerContext, parameters);
      return this.CreateActionResult(controllerContext, actionDescriptor, actionReturnValue);
 }

 在这里我们发现方法执行的关键是在actionDescriptor.Execute(controllerContext, parameters),我们知道这个actionDescriptor是个ReflectedActionDescriptor对象,

public override object Execute(ControllerContext controllerContext, IDictionary<string, object> parameters)
{
      if (controllerContext == null)
        throw new ArgumentNullException("controllerContext");
      if (parameters == null)
        throw new ArgumentNullException("parameters");
      object[] parameters1 = Enumerable.ToArray<object>(Enumerable.Select<ParameterInfo, object>((IEnumerable<ParameterInfo>) this.MethodInfo.GetParameters(), (Func<ParameterInfo, object>) (parameterInfo => ActionDescriptor.ExtractParameterFromDictionary(parameterInfo, parameters, this.MethodInfo))));
      return this.DispatcherCache.GetDispatcher(this.MethodInfo).Execute(controllerContext.Controller, parameters1);
}

最后一步,我们发现调用的是ActionMethodDispatcher对象(这个是个内部对象,它封装了我们要调用的方法对象methodInfo)的Execute方法

public object Execute(ControllerBase controller, object[] parameters)
{
      return this._executor(controller, parameters);
}

,我们发现,它是把我们当前调用的controller对象和要调用的方法的参数作为参数进行调用的,而_executor是个委托对象,我们可以通过ActionMethodDispatcher的构造函数看到它的值

public ActionMethodDispatcher(MethodInfo methodInfo)
{
      this._executor = ActionMethodDispatcher.GetExecutor(methodInfo);
      this.MethodInfo = methodInfo;
}

来自于方法GetExecutor,继续

private static ActionMethodDispatcher.ActionExecutor GetExecutor(MethodInfo methodInfo)
{
      ParameterExpression parameterExpression1 = Expression.Parameter(typeof (ControllerBase), "controller");
      ParameterExpression parameterExpression2 = Expression.Parameter(typeof (object[]), "parameters");
      List<Expression> list = new List<Expression>();
      ParameterInfo[] parameters = methodInfo.GetParameters();
      for (int index = 0; index < parameters.Length; ++index)
      {
        ParameterInfo parameterInfo = parameters[index];
        UnaryExpression unaryExpression = Expression.Convert((Expression) Expression.ArrayIndex((Expression) parameterExpression2, (Expression) Expression.Constant((object) index)), parameterInfo.ParameterType);
        list.Add((Expression) unaryExpression);
      }
      MethodCallExpression methodCallExpression = Expression.Call((Expression) (!methodInfo.IsStatic ? Expression.Convert((Expression) parameterExpression1, methodInfo.ReflectedType) : (UnaryExpression) null), methodInfo, (IEnumerable<Expression>) list);
      if (methodCallExpression.Type == typeof (void))
        return ActionMethodDispatcher.WrapVoidAction(Expression.Lambda<ActionMethodDispatcher.VoidActionExecutor>((Expression) methodCallExpression, new ParameterExpression[2]
        {
          parameterExpression1,
          parameterExpression2
        }).Compile());
      else
        return Expression.Lambda<ActionMethodDispatcher.ActionExecutor>((Expression) Expression.Convert((Expression) methodCallExpression, typeof (object)), new ParameterExpression[2]
        {
          parameterExpression1,
          parameterExpression2
        }).Compile();
}

 这个方法是把我们传进来的要调用的methodInfo对象,构建了一个表达式形式如:(ControllerBase,object[])=>ControllerBase.MethodInfo(object[]),我们发现他就是构造了_executor类型的委托的表达式,而它的类型为

private delegate object ActionExecutor(ControllerBase controller, object[] parameters);

它的调用则为ActionMethodDispatcher.Execute()方法,就是调用了当前controller对象中定义的方法,得到返回值

protected virtual ActionResult CreateActionResult(ControllerContext controllerContext, ActionDescriptor actionDescriptor, object actionReturnValue)
{
      if (actionReturnValue == null)
        return (ActionResult) new EmptyResult();
      ActionResult actionResult = actionReturnValue as ActionResult;
      if (actionResult == null)
        actionResult = (ActionResult) new ContentResult()
        {
          Content = Convert.ToString(actionReturnValue, (IFormatProvider) CultureInfo.InvariantCulture)
        };
      return actionResult;
}

得到执行结果对象ActionResult,把这个对象封装到ActionExecutedContext对象中返回,然后调用InvokeActionResultWithFilters方法,最终都会调用的方法就是InvokeActionResult方法,而这个方法中

protected virtual void InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
{
      actionResult.ExecuteResult(controllerContext);
}

会涉及到另外一个对象ActionResult,这个对象会把最终的结果呈现给客户端!

MVC 请求处理流程(二)

标签:

原文地址:http://www.cnblogs.com/lpandnn/p/2888500.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!