当前位置 > 首页 > Asp.net

Asp.net web Api源码分析-HttpActionDescriptor的创建

2012-12-4 21:46:00来源:Asp.net

紧接着上文Asp.net web Api源码分析-HttpControllerDispatcher (Controller的创建)这里已经创建好了IHttpController,现在让我们来看看它的ExecuteAsync方法,这个方法很是复杂啊。

public virtual Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
{
if (_request != null)
{
// if user has registered a controller factory which produces the same controller instance, we should throw here
throw Error.InvalidOperation(SRResources.CannotSupportSingletonInstance, typeof(ApiController).Name, typeof(IHttpControllerActivator).Name);
}

Initialize(controllerContext);

// We can't be reused, and we know we're disposable, so make sure we go away when
// the request has been completed.
if (_request != null)
{
_request.RegisterForDispose(this);
}

HttpControllerDescriptor controllerDescriptor = controllerContext.ControllerDescriptor;
ServicesContainer controllerServices = controllerDescriptor.Configuration.Services;
HttpActionDescriptor actionDescriptor = controllerServices.GetActionSelector().SelectAction(controllerContext);
HttpActionContext actionContext = new HttpActionContext(controllerContext, actionDescriptor);

IEnumerable<FilterInfo> filters = actionDescriptor.GetFilterPipeline();

FilterGrouping filterGrouping = new FilterGrouping(filters);

IEnumerable<IActionFilter> actionFilters = filterGrouping.ActionFilters;
IEnumerable<IAuthorizationFilter> authorizationFilters = filterGrouping.AuthorizationFilters;
IEnumerable<IExceptionFilter> exceptionFilters = filterGrouping.ExceptionFilters;

// Func<Task<HttpResponseMessage>>
Task<HttpResponseMessage> result = InvokeActionWithAuthorizationFilters(actionContext, cancellationToken, authorizationFilters, () =>
{
HttpActionBinding actionBinding = actionDescriptor.ActionBinding;
Task bindTask = actionBinding.ExecuteBindingAsync(actionContext, cancellationToken);
return bindTask.Then<HttpResponseMessage>(() =>
{
_modelState = actionContext.ModelState;
Func<Task<HttpResponseMessage>> invokeFunc = InvokeActionWithActionFilters(actionContext, cancellationToken, actionFilters, () =>
{
return controllerServices.GetActionInvoker().InvokeActionAsync(actionContext, cancellationToken);
});
return invokeFunc();
});
})();

result = InvokeActionWithExceptionFilters(result, actionContext, cancellationToken, exceptionFilters);

return result;
}

 

首先调用Initialize方法初始化ControllerContext、_request、_configuration,紧接着就创建一个HttpActionDescriptor

 HttpActionDescriptor actionDescriptor = controllerServices.GetActionSelector().SelectAction(controllerContext);

   在DefaultServices中有这么一句SetSingle<IHttpActionSelector>(new ApiControllerActionSelector());, 所以我们就知道controllerServices.GetActionSelector()返回的是一个 ApiControllerActionSelector实例。其中ApiControllerActionSelector的SelectAction 实现也比较简单:

    public virtual HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
        {
            ActionSelectorCacheItem internalSelector = GetInternalSelector(controllerContext.ControllerDescriptor);
            return internalSelector.SelectAction(controllerContext);

        }

我们首先来看看GetInternalSelector方法实现:、

   private ActionSelectorCacheItem GetInternalSelector(HttpControllerDescriptor controllerDescriptor)
        {
            // First check in the local fast cache and if not a match then look in the broader
            // HttpControllerDescriptor.Properties cache
            if (_fastCache == null)
            {
                ActionSelectorCacheItem selector = new ActionSelectorCacheItem(controllerDescriptor);
                Interlocked.CompareExchange(ref _fastCache, selector, null);
                return selector;
            }
            else if (_fastCache.HttpControllerDescriptor == controllerDescriptor)
            {
                // If the key matches and we already have the delegate for creating an instance then just execute it
                return _fastCache;
            }
            else
            {
                // If the key doesn't match then lookup/create delegate in the HttpControllerDescriptor.Properties for
                // that HttpControllerDescriptor instance
                ActionSelectorCacheItem selector


  • 简单好用的联动下拉控件

    2007-3-12 15:14:00

    摘要: 自己好几个地方要用到联动控件,项目又不想用Ajax,又想在客户端实现联动而不刷新,还想在服务器端用相似的代码来绑定项,还想在服务器端用相同的代码得到选定的值(也就是值可以提交),想了想,还是

  • 为XNA制做安装程序(一)综述

    2009-11-11 23:37:00

    阅读: 154 评论: 0 作者: 风海迷沙 发表于 2009-11-11 21:16 原文链接 如果客户机上安装了所需要的组件是最好不过的了,最简单的方法就是在Release模式下将bi

  • NHibernate3剖析:Query篇之NHibernate.Linq自定义扩展

    2010-8-12 12:54:00

    作者: 李永京 发表于 2010-08-11 20:05 原文链接 阅读: 731 评论: 14 本节内容 系列引入 概述 Linq

  • Net设计模式之观察者模式(Observer Pattern)

    2010-1-5 0:52:00

    阅读: 11 评论: 0 作者: 灵动生活 发表于 2010-01-05 00:14 原文链接 一、观察者模式简介( Brief Introduction )

  • 如何招到优秀的程序员

    2010-7-22 8:01:00

    作者: Justina Chen 发表于 2010-07-21 22:49 原文链接 阅读: 676 评论: 16 看过“如何招到烂程序员”,恰好我也正需要招聘一些

  • .net中如何调用jar文件夹包

    2011-1-14 8:36:00

    同事提供了一个.jar包,我想将其生成DLL,或使用其它方法,可以在。NET中调用该包中的方法。如有操作过的,请指点下,谢谢。

  • Podcasting Recording Hardware

    2010-1-29 14:59:00

    Mario Cardinal and I have been recording the Visual Studio Talk Show podcast for more then 5 yea

  • 【ASP.NET】困扰我多年的URL参数设置问题

    2011-3-9 13:02:00

    URL参数一直以来困扰着我。始终没有一个完美的解决方案!考虑到网页的安全性有些地方不得不做以限制。由于本身对这个地方没有经验,所以前来问问各路高手 你们是怎么处理这个问题的。我把我所遇到的问题说一下

  • 升级到ActiveSync 4.5后“可能”遇到的网络连接问题,以及解决方法

    2007-4-10 9:28:00

    摘要: 原本用的AS的版本是4.1。在运行带有Replication功能的测试用例都是正常,sdf数据库文件都能同步更新数据。但自从安装了AS 4.5时,问题就出现了(在安装升级的中间,我还进行了其

  • Step By Step 一步一步写网站[1] —— 填加数据

    2007-3-24 14:59:00

    摘要: 填加数据是一个项目必不可少的部分,也是一个基础操作,使用也是最频繁的。那么您是怎么实现添加数据的呢?添加数据可以分为几种情况。1、单表添加,不需要事务。最简单最常见2、多表(主从表)添加,不