当前位置 > 首页 > 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


  • .NET一个线程更新另一个线程的UI(两种实现方法)

    2012-11-12 19:36:00

    本片博文接上一篇: .NET多线程执行函数 ,给出实现一个线程更新另一个线程UI的两种方法。 Winform中的控件是绑定到特定的线程的(一般是主线程),这意味着从另一个线程更新主线程的控件不能直

  • Expression Blend Linked Resources Error "Unable to find the specified file"

    2009-9-25 1:29:00

    If you ever receive an Unable to find the specified file error in Expression Blend while trying to

  • 纯CSS相册

    2009-9-18 12:13:00

    摘要: 最近都在研究javascript,CSS有点生疏了。是时候拿个东西练练手。<dl> <dt> <a href=#index6>6</a>&l

  • Command Level Virtualization ('Empty Client')

    2009-3-25 17:27:00

    The following article on the Visual WebGui Technology section explains the Visual WebGui Command

  • re: 分享一額可以免費下載圖書的網站!!!!!!!!!!

    2007-9-23 7:30:00

    我想看书,我要看书,因此我来了~! 胡冰峰 2007-09-23 04:42 发表评论

  • 单一职责原则--SRP

    2007-3-2 15:55:00

    摘要: 就一个类而言,应该只专注于做一件事和仅有一个引起它变化的原因。 阅读全文 FrankFei 2007-03-02 15:21 发表评论

  • 我最近一个项目的架构与演变过程

    2009-9-3 21:21:00

    摘要: 想发帖了,记录下最近做的一个项目的架构与演变过程。首先我不是个爱胡侃的人,所以拿点实际的例子说事,架构并不复杂。 最近做完了一个Web项目,因为这个项目是我们学校的一个对外的门户,并且学校方

  • .net向mono移植遇到的两个问题及解决方法

    2011-11-18 21:12:00

    序论:关于mono的介绍可以 猛击这里 了解!如果你因为licence的问题而对mono望而却步,你可以仔细看下 这里 ,之后你就会大胆的去用了! 最近为了练习做了一个简单的三层架构的信息管理系

  • 向IE6说不

    2009-8-14 5:58:00

    摘要: 最近抵制IE6的运动似乎多了起来,老赵也在自己的博客呼吁抵制IE6,然而和国外各大流行网站的积极响应不同的是,国内一片风平浪静,而且还有很多人反对废弃IE6(见老赵博客响应回帖)。作为一个2

  • Nhibernate入门

    2007-8-15 22:01:00

    摘要: 对大部分Nhibernte操作,都写了一个Demo,映射文件全部手写(手疼),看完后会对Nhibernte有个全面的了解。不想看文字的,可以看看附件中的代码。什么是Nhibernate Nh