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

  • .net DLL之间是通过AssemblyVersion建立引用关系的

    2011-11-12 18:34:00

    AssemblyVersion对程序集间的引用很重要,此版本号一般不要随便改,也不要让其自动生成,如果项目很多,类库间引用很多你这么做了的话,很可能把dll搞乱,解释:   类库ClassA设置

  • SharePoint2007的字段级权限

    2007-6-4 1:25:00

    总有人问我们,如何控制SharePoint的字段级权限,意思就是说,比如一个列表记录或者一个文档,我们想让这个记录的某个字段只让某个人或某些人可以编辑。 但我们之前的答案一直是“这不是Share

  • 39

    2007-7-11 0:06:00

    An old favorite of mine, Jack Benny, used to be 39 forever. Today, I turned that age. Time flies ...

  • MethodViz 0.2

    2007-4-9 12:55:00

    See this post for introduction to MethodViz. Briefly " MethodViz is a simple method hierar

  • Add Label To jQuery Slider Handle

    2010-1-13 3:23:00

    While in process of using the jQuery UI Slider in creating an alpha slider for a rolodex interface

  • VirtualBox 虚拟机 Debian系统上安装Cassandra步骤及遇到的问题

    2010-3-11 13:43:00

    阅读: 709 评论: 2 作者: Birdshover 发表于 2010-03-10 18:51 原文链接 本文记录一下我在VirtualBox 虚拟机 Debian系统上安装Cassa

  • 通过代码配置 Log4net

    2011-5-10 14:02:00

    最近将项目的异常日志模块改造成log4net。在Asp.net MVC3 中的改造非常简单,我们只要继承HandleErrorAttribute类使用自定义类, 使用特性即可统一处理MVC co

  • SequenceViz 0.3 :: Namespaces and Pie Chart

    2007-4-18 2:13:00

    With the help of Mike and Steve , finally there are few visitorscoming to the sitelooking for S

  • jQuery-Selectors(选择器)的使用(七、子元素篇)

    2009-12-8 16:11:00

    阅读: 13 评论: 0 作者: code-cat 发表于 2009-12-08 15:35 原文链接 .div { width:95%; margin-left:15px;

  • .net托管环境下struct实例字段的内存布局(Layout)和大小(Size)

    2007-4-15 10:06:00

    摘要: 默认(LayoutKind.Sequential)情况下,CLR对struct的Layout的处理方法与C/C++中默认的处理方式相同,即按照结构中占用空间最大的成员进行对齐(Align);