一.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. UESTC482-Charitable Exchange-bfs优先队列

    #include <cstring> #include <algorithm> #include <iostream> #include <queue> ...

  2. 洛谷P2670扫雷游戏题解

    题目 这道题是一个简单的模拟搜索题,可以把每个雷的位置都记作1. 这样就可记录出数字啦 #include<iostream> #include<cstring> using n ...

  3. Java的equals方法,首先要判断类型是否相同

    如下代码,Long 和Integer 进行比较: Integer aa = 1; Long bb= 1L; System.out.println(aa.equals(bb)); 输出为:false 查 ...

  4. Scratch 简单的小游戏 --- 碰碰球

    Scratch 简单的小游戏 --- 碰碰球 ================================ 积木脚本块的简要分类: 1. 角色 2. 背景 3. 角色和背景组成的场景 4. 挡板角 ...

  5. 【POJ 1001】Exponentiation (高精度乘法+快速幂)

    BUPT2017 wintertraining(15) #6A 题意 求\(R^n\) ( 0.0 < R < 99.999 )(0 < n <= 25) 题解 将R用字符串读 ...

  6. 利用纯粹的CSS3替代小图标---向右箭头

    1.向右的箭头>  . 看到很多网站里面向右的箭头都是图片代替的,但是为了网站的性能,我们一般的原则是能够避免使用图片的尽量不用图片   比如看下携程个人中心首页面,向右的箭头 其实现思路是这样 ...

  7. CPU监控 解题报告

    CPU监控 这种题就需要小黄鸭调试法,不行就重构,动态gdb可能会死人,一堆tag的... 维护历史最值的一个核心是历史最值tag,它的意义是从上一次这个点下放tag之后到当前时刻的这个点的tag达到 ...

  8. Nginx优化文件编写

    server_tokens off; #并不会让nginx执行的速度更快,关闭它可隐藏错误页面中的nginx版本号charset utf-8,gbk; #字符#sendfile on;#tcp_nop ...

  9. CodeFroces-- 514.div2.C-Sequence Transformation

    题目链接 :514.div2.C-Sequence Transformation #include<bits/stdc++.h> using namespace std; #define ...

  10. mysql json 使用 类型 查询 函数

    一,对记录的操作 1.创建有json字段的表 -- 创建表 ) , info JSON); 2.插入记录 -- 插入含有json数组的记录 , , "abc", NULL, TRU ...