现在的位置: 主页 > 主打产品 > 文章列表

【Web API系列教程】2.2 — ASP.NET Web API中的路由

作者:沈阳市沈河区金瑞龙美术社 来源:www.jrlgg.com 发布时间:2017-09-02 11:47:00
 

【Web API系列教程】2.2 — ASP.NET Web API中的路由和动作选择机制

这篇文章描述了ASP.NET Web API如何将HTTP请求路由到控制器上的特定动作。

备注:想要了解关于路由的高层次概述,请查看Routing in ASP.NET Web API。

这篇文章侧重于路由过程的细节。如果你创建了一个Web API项目并且发现一些请求并没有按你预期得到相应的路由,希望这篇文章有所帮助。

路由有以下三个主要阶段:

将URI匹配到路由模板 选择一个控制器 选择一个动作

你可以用自己的习惯行为来替换其中一些过程。在本文中,我会描述默认行为。在结尾,我会指出你可以自定义行为的地方。

路由模板(Route Templates)

路由模板看起来和URI路径非常相似,但是它能包含用大括号指明的占位符。

"api/{controller}/public/{category}/{id}"

当你创建了一个路由,你为一些或全部占位符提供默认的值:

defaults: new { category = "all" }

你也可以提供一些约束(constraints),它限制了URI字段如何才能匹配一个占位符:

constraints: new { id = @"\d+" } // Only matches if "id" is one or more digits.

框架会尽力将URI路径中的字段匹配到模板中。模板中的文字必须准确匹配。一个占位符可以匹配多个变量,除非你指定了约束。框架不会匹配URI的其他部分,比如主机名或查询参数。框架仅仅在用于匹配URI的路由表中选择第一个路由。

这里有两个特殊的占位符:”{controller}“和“{action}”。

“{controller}“提供了控制器的名称。 “{action}“提供了动作的名称。在Web API中,通过会忽略“{action}”。 Defaults

如果你提供了默认的API,路由将会匹配缺少这些的URI。例如:

routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{category}", defaults: new { category = "all" } );

对于URI http: //localhost/api/products 将会匹配这个路由。{category} 字段会被分配默认值 all。

路由字典(Route Dictionary)

如果框架发现了URI的一个匹配,它会创建一个包含了每个占位符适用的值的字典集合。键是不包含大括号的占位符名称。值是提取自URI路径或者默认表单。该字典被存储在IHttpRouteData对象中。

在路由匹配阶段,“{controller}“和”{action}“占位符会被像其他占位符一样对待。它们被同其他值一起简单地存储在字典中。

对于defaults,它可以有一个特殊值RouteParameter.Optional。如果一个占位符被分配到这个值,那么这个值不会被添加到路由字典中。例如:

routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{category}/{id}", defaults: new { category = "all", id = RouteParameter.Optional } );

对于URI路径“api/products”,路由字典将会包含:

controller:“products” category:“all”

然而对于“api/products/toys/123”,路由字典将会包含:

controller:“products” category:“all” id:“123“

对于defaults,它同样也会包含一个没有在路由模板中任何地方出现的值。如果路由匹配了,这个值会被存储在字典中。例如:

routes.MapHttpRoute( name: "Root", routeTemplate: "api/root/{id}", defaults: new { controller = "customers", id = RouteParameter.Optional } );

如果URI路径“api/root/8”,字典将会包含两个值:

controller:”customers“ id:“8” 选择控制器(Selecting a Controller)

控制器的选择由IHttpControllerSelector.SelectController方法来处理。这个方法需要传入一个HttpRequestMessage实例并返回HttpControllerDescriptor对象。默认的实现是由DefaultHttpControllerSelector类来实现的。这个类使用了一个简单的算法:

在路由字典中查找键”controller“。 提取出这个键对应的值,并添加字符串“Controller”以得到控制器的类型名 用这个类型名来查找一个Web API控制器

例如,如果路由字典包含键值对“controller”=“products”,那么控制器类型就是“ProductsController”。如果这里不存在匹配的类型,或存在多个匹配,那么框架就会向客户端发送一个错误。

对于步骤3,DefaultHttpControllerSelector会使用IHttpControllerTypeResolver接口来得到Web API控制器类型的列表。IHttpControllerTypeResolver的默认实现会返回(a)实现IHttpController,(b)不是抽象的,(c)名称以“Controller“结尾的所有公共的类。

动作选择

在选择控制器之后,框架会通过调用IHttpActionSelector.SelectAction方法来选择动作。这个方法需要传入一个HttpControllerContext参数以及返回一个HttpActionDescriptor对象。

默认的实现由ApiControllerActionSelector类来提供。为了选择一个动作,它会按以下要求来查找:
1) 请求的HTTP方法
2) 路由模板中的“{action}“占位符(如果存在)
3) 控制器中动作的参数

在查看选择算法之前,我们需要理解关于控制器动作的一些东西。

控制器中的哪些方法会被认为是“动作“?当选择一个动作时,框架仅仅在控制器中查找公共的实例方法。当然了,它会排除一些”特殊“的方法(构造函数,事件,操作重载等等)和继承自ApiController类的方法。

HTTP方法。框架只会选择匹配请求的HTTP方法的动作,它取决于以下几点:

你可以用某个属性来具体说明是HTTP方法:AcceptVerbs,HttpDelete,HttpGet,HttpHead,HttpOptions,HttpPatch,HttpPost或HttpPut。 或者,如果一个控制器方法的名称以”Get”,“Post“,”Put“,”Delete“,”Head“,”Options“或”Patch“开始,那么按照约定该动作就支持HTTP方法。 如果不包含以上几点,但支持POST的方法。

参数绑定。参数绑定是指Web API如何如何为参数创建一个值。这里是参数绑定的默认规则:

简单类型直接从URI中提取 复杂类型从请求体重提取

简单类型包括所有.NET框架基本类型(.NET Framework primitive types),再加上DateTime、Decimal、Guid、String和TimeSpan。对于每个动作,最多有一个参数可以读取请求体。

备注:重载默认绑定规则也是有可能的。查看WebAPI Parameter binding under the hood.

有了以上这些背景知识,这里是动作选择的算法:

基于HTTP请求方法匹配到的控制器创建一个动作列表。 动作路由字典包含“action“记录,移除其名字不匹配该值的动作。

企业建站2800元起,携手武汉肥猫科技,做一个有见地的颜值派!更多优惠请戳:武汉网站建设 http://wuhan.45qun.com

  • 上一篇:卡汀财经分享—摩根士丹利告诉你,他们都在读哪些金融
  • 下一篇:最后一页
  •