一.Web API中的路由概念

路由的作用用一句话说明:通过request的uri找到处理该请求的Controller,Action,以及给Action的参数赋值。

一些路由的基本概念:

      route:路由规则对象,存放了路由的规则;
    routeCollection:路由规则集合,存放了route对象;
    route template:路由模板,形式和uri接近,用于匹配uri;
    route dictionary:路由字典,找到uri匹配的route template后创建的用于存储route template中占位符值的字典;
    RouteData:真正存放路由信息的对象,保存了Controller、Action的值等;
    Http method:请求api的方式,如get/post/put/delete等。

web api中默认的路由:

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

   route collection 中的每个 route (路由规则对象)都包含一个路由模板( route template )。Web API的默认路由模板是“api / {controller} / {id}”。在此模板中,“api”是文字路径段,{controller}和{id}是占位符变量。当Web API框架收到HTTP请求时,它会尝试将URI与route table中的某个route template进行匹配。如果没有route匹配,则客户端收到404错误。

二、路由过程

路由的过程有三步:
  1.通过uri匹配到route template
  2.获取对应的Controller
  3.获取对应的Action

第一步:通过uri匹配到route template

  路由模板看起来很像uri地址,但是它包含了一些占位符,下边我们通过 WebApiConfig.cs 添加一个route(路由规则),名字是MyRoute,当没有controller时,默认的controller时Home;自定义参数id添加了一个约束:id必须是数字。当我们添加下边的代码后,routeCollection就多了一个route对象。

config.Routes.MapHttpRoute(
  name: "DefaultApi",
  routeTemplate: "api/{controller}/{id}",
  defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
  name: "MyRoute",
  routeTemplate: "api/{controller}/{action}/{id}",
  //可以给占位符提供默认值
  defaults: new { controller = "Home" },
  //可以给占位符添加约束,只有id是数字时才匹配这个路由规则
  constraints: new { id = @"\d+" }
);

  当框架接受到一个request时,会查找uri匹配的路由模板,找到路由模板后会创建一个 Route Dictionary 对象,这个对象里包含每个占位符的值,key是占位符的名字,值从uri中或者默认值中获取。这个字典对象存储在IHttpRouteData对象中。
一个栗子:uri为api/Products/FindProduct/1,匹配成功MyRoute的routeTemplate成功,创建的路由字典中包含了

  controller:Products
  action:FindProduct
  id:

第二步:获取Controller

Controller的默认方法很简单:
  找到路由字典中的controller,在controller的值后天追加“Controller”。如我们路由字典中的controller的值是Products,那么找的Controller就是 Products+"Controller"=ProductsController。

第三步:获取Action

  获取Action时,Web API会查看HTTP方法,然后查找名称以该HTTP方法名称开头的action。例如,对于GET请求,Web API会查找以“Get ...”开头的操作,例如“GetContact”或“GetAllContacts”。此约定仅适用于GET,POST,PUT和DELETE方法。您可以使用控制器上的属性启用其他HTTP方法。当找到多个方法符合http method时,匹配参数符合最多的那个。

三、覆盖默认HttpMethod

3.1  使用HttpMethod特性 

  当我们使用[HttpGet] [HttpPost] [HttpPut] [HttpDelete]特性修饰action时,web api接收到一个请求时,也会按照http method进行查找,如用[HttpGet]修饰action,我们以get的形式访问http://xxx:xx/Products时,会找到下边栗子的FindProduct(id)。注意:如果没有属性标签,也不以Http method开头,那么默认为post。
  一个栗子:

public class ProductsController : ApiController
{
  [HttpGet]
  public Product FindProduct(int id) {}
}

3.2  使用AcceptVerbs和NonAction特性 

  如果我们想让一个方法在多个Http method中匹配,如我们使用get或者post请求时都访问方法FindProduct(id),怎么去设置呢?可以使用AcceptVervs进行设置,如下设置后当我们使用get或者post请求api/products/都会匹配到方法FindProduct

public class ProductsController : ApiController
{
  [AcceptVerbs("GET", "POST")]
  public Product FindProduct(id) { }
}

怎么让controller中的普通方法,不被匹配到呢?只需要在方法上边添加 [NonAction] 即可

[NonAction]
public string GetStr(Product p){
return p.Name;
}

小结:以http://xxxx:xx/Products/1 简单说明webapi中路由过程:我们设定的 Route 都存放的RouteCollection中,当webapi框架到一条request后,通过request的 uri (采用的方法是 routes.MapRoute )匹配route中的 route template ,如果有匹配的话,生成一个 Route Dictionary 对象,这个字典对象中存储了route template的占位符的值;接下来我们从route dictionary中查找controller值(Products),通过字符串拼接找到处理请求的ProductsController;通过request的 http method (如这里采用的get方法),查找ProductsController中的Action中匹配get的,这时我们找到了GetAllProducts和GetProduct(int id),因为我们传入有额外的项1,在GetProduct匹配的参数1个,而在GetAllProducts中匹配的参数时0个,按匹配参数最多的进行匹配所有最终匹配的action是GetProduct,最后把额外的1赋值给GetProduct的参数id。一次路由到这里就结束了。

Web API中的路由(一)——约定路由的更多相关文章

  1. 【ASP.NET Web API教程】4.1 ASP.NET Web API中的路由

    原文:[ASP.NET Web API教程]4.1 ASP.NET Web API中的路由 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的内容. ...

  2. ASP.NET Web API中的Routing(路由)

    [译]Routing in ASP.NET Web API 单击此处查看原文 本文阐述了ASP.NET Web API是如何将HTTP requests路由到controllers的. 如果你对ASP ...

  3. Web API中的路由(二)——属性路由

    一.属性路由的概念 路由让webapi将一个uri匹配到对应的action,Web API 2支持一种新类型的路由:属性路由.顾名思义,属性路由使用属性来定义路由.通过属性路由,我们可以更好地控制We ...

  4. ASP.NET WEB API 中的路由调试与执行过程跟踪

    路由调试 RouteDebugger 是调试 ASP.NET MVC 路由的一个好的工具,在ASP.NET WEB API中相应的有 WebApiRouteDebugger ,Nuget安装 Inst ...

  5. 在 ASP.NET Web API 中,使用 命名空间(namespace) 来作为路由的参数

    这个问题来源于我想在 Web API 中使用相同的控制器名称(Controller)在不同的命名空间下,但是 Web API 的默认 路由(Route) 机制是会忽略命名空间的不同的,如果这样做,会看 ...

  6. Web APi入门之Self-Host寄宿及路由原理(二)

    前言 刚开始表面上感觉Web API内容似乎没什么,也就是返回JSON数据,事实上远非我所想,不去研究不知道,其中的水还是比较深,那又如何,一步一个脚印来学习都将迎刃而解. Self-Host 我们知 ...

  7. Web APi入门之Self-Host寄宿及路由原理

    前言 刚开始表面上感觉Web API内容似乎没什么,也就是返回JSON数据,事实上远非我所想,不去研究不知道,其中的水还是比较深,那又如何,一步一个脚印来学习都将迎刃而解. Self-Host 我们知 ...

  8. Web APi入门之Self-Host寄宿及路由原理 【转载】

    前言 刚开始表面上感觉Web API内容似乎没什么,也就是返回JSON数据,事实上远非我所想,不去研究不知道,其中的水还是比较深,那又如何,一步一个脚印来学习都将迎刃而解. Self-Host 我们知 ...

  9. Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化

    9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...

随机推荐

  1. K - Transformation HDU - 4578 线段树经典题(好题)

    题意:区间  加   变成定值 乘  区间查询:和 平方和 立方和 思路:超级超级超级麻烦的一道题  设3个Lazy 标记分别为  change 改变mul乘 add加  优先度change>m ...

  2. F - Count the Colors ZOJ - 1610 线段树染色(染区间映射)

    题意:给一段0-8000的线段染色 问最后 颜色x 有几段 题解:标准线段树  但是没有push_up  最后查询是单点按顺序查询每一个点 考虑过使用区间来维护不同的线段有多少种各色的线段  思路是 ...

  3. 「Splay」区间翻转

    传送门:>Here< 解法分析 用splay来维护这个序列. 一直没有搞明白的是,这里的splay的节点究竟维护的是什么?是权值吗?肯定不是,因为区间是会翻转的,如果维护权值的话很快平衡树 ...

  4. sublime3添加verilog自动补全代码段

    前言 sublime默认的verilog自动补全十分垃圾,不过提供了代码段这个功能,你可以自己写个重用率高的代码段减轻工作量.写个模板当tb也很爽啦. 流程 1.打开user文件夹,创建verilog ...

  5. RSS阅读器“阅读原文”报错400

    问题 使用SpringMVC框架,实现了RSS订阅,在FoxMail的RSS订阅页面,点击[阅读原文],报错400 . 每个RSS文章的链接是:https://jiashubing.cn/forum/ ...

  6. ATR102E Stop. Otherwise... [容斥]

    第一道容斥 \(ans[i] = \sum_{j = 0}^{min(cnt, n / 2)} (-1)^j \tbinom{cnt}{j} \tbinom{n - 2*j + k - 1}{k - ...

  7. 【arc073e】Ball Coloring(线段树,贪心)

    [arc073e]Ball Coloring(线段树,贪心) 题面 AtCoder 洛谷 题解 大型翻车现场,菊队完美压中男神的模拟题 首先钦定全局最小值为红色,剩下的袋子按照其中较大值排序. 枚举前 ...

  8. SQL查询语句的进阶使用

    MySQL的进阶使用 sql语句一些功能的使用 导入现有大量数据文件步骤 1) 把*.sql文件拷贝到Linux某一位置(例如Desktop) 2) Linux命令行进入该位置 cd ~/Deskto ...

  9. sshd启动报错Could not load host key

    ~ # /usr/sbin/sshd Could not load host key: /etc/ssh/ssh_host_rsa_key Could not load host key: /etc/ ...

  10. Flask 键盘事件

    <div class="container" style="margin-top: 300px; "> <div class="ro ...