当前位置 > 首页 > Asp.net

Asp.net web Api源码分析-HttpControllerDispatcher (Controller的创建)

2012-12-4 16:32:00来源:Asp.net

紧接着上文Asp.net web Api源码分析-HttpServer的创建最后我们提到了一个HttpRoutingDispatcher,一看这个类的名字我想我们也就能猜到它是干什么的吧。查找路由信息,那么找到路由后干什么了,是不是就该调用handler了?

首先还是让我们来看看HttpRoutingDispatcher的SendAsync方法


  protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            // Lookup route data, or if not found as a request property then we look it up in the route table
            IHttpRouteData routeData;
            if (!request.Properties.TryGetValue(HttpPropertyKeys.HttpRouteDataKey, out routeData))
            {
                routeData = _configuration.Routes.GetRouteData(request);
                if (routeData != null)
                {
                    request.Properties.Add(HttpPropertyKeys.HttpRouteDataKey, routeData);
                }
                else
                {
                    return TaskHelpers.FromResult(request.CreateErrorResponse(
                        HttpStatusCode.NotFound,
                        Error.Format(SRResources.ResourceNotFound, request.RequestUri),
                        SRResources.NoRouteData));
                }
            }

            RemoveOptionalRoutingParameters(routeData.Values);

            var invoker = routeData.Route.Handler == null ? _defaultInvoker : new HttpMessageInvoker(routeData.Route.Handler, disposeHandler: false);
            return invoker.SendAsync(request, cancellationToken);

        }

首先这里先从HttpRequestMessage中获取路由信息,如果不能获取则调用_configuration.Routes.GetRouteData来获取路由信息,默认情况下这里是可以获取到路由信息(因为在HttpControllerHandler的BeginProcessRequest方法中有这么一句 request.Properties[HttpPropertyKeys.HttpRouteDataKey] = _routeData;)然后调用RemoveOptionalRoutingParameters方法来移除路由中的可选参数。

这里的routeData我们知道它是在HttpControllerHandler的构造函数中创建的一个HostedHttpRouteData实例,其Route属性是一个HostedHttpRoute实例,routeData.Route.Handler就是我们路由中注册的handler,默认情况下我们没有注册自己的handler,所以这里的invoker=_defaultInvoker,这里的_defaultInvoker=      new HttpMessageInvoker(new HttpControllerDispatcher(configuration)),所以调用invoker的SendAsync方法,其实就是调用HttpControllerDispatcher的SendAsync方法

HttpControllerDispatcher这个名称我们就可以猜测到它是把当前http请求交给特定的Controller来处理。HttpControllerDispatcher的SendAsync方法差不多就是一个内联函数,直接调用内部的SendAsyncInternal方法:

private Task<HttpResponseMessage> SendAsyncInternal(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request == null)
{
throw Error.ArgumentNull("request");
}

IHttpRouteData routeData = request.GetRouteData();
Contract.Assert(routeData != null);
HttpControllerDescriptor httpControllerDescriptor = ControllerSelector.SelectController(request);
if (httpControllerDescriptor == null)
{
return TaskHelpers.FromResult(request.CreateErrorResponse(
HttpStatusCode.NotFound,
Error.Format(SRResources.ResourceNotFound, request.RequestUri),
SRResources.NoControllerSelected));
}

IHttpController httpController = httpControllerDescriptor.CreateController(request);
if (httpController == null)
{
return TaskHelpers.FromResult(request.CreateErrorResponse(
HttpStatusCode.NotFound,
Error.Format(SRResources.ResourceNotFound, request.RequestUri),
SRResources.NoControllerCreated));
}

// Set the controller configuration on the request properties
HttpConfiguration requestConfig = request.GetConfiguration();
if (requestConfig == null)
{
request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, httpControllerDescriptor.Configuration);
}
else
{
if (requestConfig != httpControllerDescriptor.Configuration)
{
request.Properties[HttpPropertyKeys.HttpConfigurationKey] = httpControllerDescriptor.Configuration;
}
}

// Create context
HttpControllerContext controllerContext = new HttpControllerContext(httpControllerDescriptor.Configuration, routeData, request);
controllerContext.Controller = httpController;
controllerContext.ControllerDescriptor = httpControllerDescriptor;

return httpController.Execu

  • New Request validation features in ASP.Net 4.5

    2011-12-20 14:10:00

    (This article is based on ASP.Net 4.5 developer preview, when the version is released there may be

  • Asp.Net无刷新上传并裁剪头像

    2011-11-29 13:29:00

    开发网站几乎都做过上传图片并截图,做个无刷新Asp.Net上传并截图示例 实现功能: 1.选择文件,自动上传并生成缩放图(上传带进度条),形成预览图 2.在预览区,实现鼠

  • .NET插件系统——不实例化获取插件信息和可视化方法

    2012-2-12 18:56:00

    面临的问题 在开发插件系统中,我们通常会面临这样的问题: 一些功能并不是在开启时就要被使用的,例如VS中的大量功能对一个大部分程序员来说用不着

  • 忽悠激励法--股份制

    2009-11-24 16:55:00

    阅读: 88 评论: 6 作者: songsoft 发表于 2009-11-24 16:41 原文链接 忽悠激励法 -- 股份制 真滴?假滴? 又听老板说要搞股份制,

  • 我写项目的思路和“自然架构”

    2009-5-21 21:22:00

    我写项目的思路 三层的思路是要把页面(UI、数据显示)、业务逻辑、数据处理(也叫持久化)分离开来处理,思路自然是好的,但是一到了实际应用中,好多人就会遇到一点小小的问题,于是

  • 5.生产务必研究出套路 -- 建造者模式 (闪电咂摸设计模式傻瓜化)

    2009-7-7 0:17:00

    书接上回。 上文书提到农民乙开拓进取的精神,俺们村人那是相当的佩服。 据苦娃讲,农民乙还有个优点呢,那就是无比的勤奋。 “山蛋蛋开花红艳艳”公司成立以来,农

  • asp.net控件设计时支持(3)

    2007-5-15 0:40:00

    摘要: 示例代码 都已经忘了更新了,感觉非常愧疚啊.现在努力补上 上篇很偷懒的写了自动格式设置. 把没讲完的补上.一.智能标记先看一张图.GridView右侧的小三角可以很轻松的帮助我们设置常用的属

  • 项目经理成长日记(7)——说是细,做的粗

    2009-4-1 8:06:00

    摘要: 估计绝大部分的公司都在提倡一个口号:“注重细节。”但是往往是口号容易行,行动却是千辛万苦,何谓细节?也就是自身工作的每一个环节、每一道流程的琐碎小事,而这些小事又常常容易被人忽略。有很

  • 老南瓜的困惑:搞不清SQL SERVER 2005 中的用户

    2009-4-3 1:05:00

    摘要: 老南瓜的困惑:搞不清SQL SERVER 2005 中的用户  工作中总有许多的困惑,经常搞一搞,就不再困惑了。―――老南瓜  老南瓜一直对SQL Server 2005里的用户的概念不是

  • .Net程序员面试 中级篇 (回答Scott Hanselman的问题)

    2010-11-14 9:20:00

    继《 .Net 程序员面试 C# 语言篇 (回答Scott Hanselman的问题) 》跟《 .Net程序员面试 每个人都应知道篇 (回答Scott Hanselman的问题) 》之后,今天回答S