Web API 路由机制分析

  • Web API项目的路由机制是在App_Start文件下自动生成一个WebApiConfig.cs文件
 1 public static class WebApiConfig
 2 {
 3     public static void Register(HttpConfiguration config){
 4         // Web API 路由
 5         config.MapHttpAttributeRoutes();//启动特性路由
 6         config.Routes.MapHttpRoute(
 7             name: "DefaultApi",
 8             routeTemplate: "api/{controller}/{id}",
 9             defaults: new { id = RouteParameter.Optional }
10         );
11     }
12 }
13 //下面是方法参数
14 public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints);
  • MapHttpRoute()方法参数
    • name:路由的名称,保证不能重复
    • routeTemplate:路由模板,比如"api/{controller}/{id}"这个路由,"api"是固定部分,区别一下这个是Web API项目;"{controller}"这个是控制器的占位符,在真正URL中这里是控制器名称;"{id}"是参数的占位符
    • defaults"new { id = RouteParameter.Optional }"这句话表示id这个参数是可选的,还可以设置controller="TestRoute",这样如果路径是http://localhost:61218/api,也可以访问到
    • constraints:表示路由约束,一般是一个约束路由模板的正则表达式,比如设置constraints: new { id = @"d+" } 表示id参数为一个到多个整数,访问http://localhost:61218/api/TestRoute/a返回404报错
 1 public class TestRouteController : ApiController
 2 {
 3     [HttpGet]//http://localhost:61218/api/TestRoute
 4     public object GetAll(){
 5         return "Success";
 6     }
 7     [HttpGet]//http://localhost:61218/api/TestRoute/1
 8     public object GetById(int id){
 9         return "Success" + id;
10     }
11
  • WebApiConfig.cs文件中自定义路由模板
 1 config.Routes.MapHttpRoute(
 2     name: "ActionApi",
 3     routeTemplate: "actionapi/{controller}/{action}/{id}",
 4     defaults: new { id = RouteParameter.Optional }
 5 );
 6 config.Routes.MapHttpRoute(
 7     name: "TestApi",
 8     routeTemplate: "testapi/{controller}/{ordertype}/{id}",
 9     defaults: new { ordertype = "orderby", id = RouteParameter.Optional }
10 ); 
1 [ActionName("TestActionName")]
2 [HttpGet]
3 public object GetById(int id){
4     return "Success" + id;
5
  • 路由请求过程
    • Web API服务启动之后,会执行全局配置文件Global.asax.cs中的Application_Start方法,会通过参数委托去执行WebApiConfig.cs文件中Register方法,将所有配置的路由信息添加到HttpRouteCollection对象中
    • 当发送请求Web API服务器的时候,请求会首先被UrlRoutingModule监听组件截获,然后将截获的请求在Routes路由集合中匹配到对于的路由模板(如果匹配不到,则返回404),得到对于的IHttpRoute对象
    • 将IHttpRoute对象交给当前请求的上下文对象RequestContext处理,根据IHttpRoute对象里面的url匹配到对应的控制器(根据DefaultHttpControllerSelector类的SelectController()方法,该类继承于IHttpControllerSelector接口)
    • 如果路由模板中配置了{action},则直接就能从url中找到action名称匹配方法,反之没有配置,则首先根据http请求的类型(get/post/put/delete,可以通过特性进行设置)和参数找到对应的action
1 //该方法支持两种不同的请求,通过AcceptVerbs特性支持多种请求
2 [AcceptVerbs("GET", "POST")]
3 public IHttpActionResult GetById(int id){
4     return Ok<string>("Success" + id );
5
  • 特性路由
    • WebApiConfig.cs的Register()方法中config.MapHttpAttributeRoutes()启动特性路由
    • Route特性:设置每个方法的访问路径,还可以使用"{}"占位符传递参数,同时可以使用约束和默认值(比如{id:int=3})
    • RoutePrefix特性:设置路由前缀,比如下面的url前缀都是api/TestRoute2
 1 [RoutePrefix("api/TestRoute2")]
 2 public class TestRoute2Controller : ApiController
 3 {
 4     // [Route("~/")]//无论加不加前缀都可以通过 / 访问该页面
 5     [Route("")]
 6     [HttpGet]//http://localhost:61218/api/TestRoute2
 7     public IHttpActionResult GetAll(){
 8         return Ok<string>("Success");
 9     }
10     [Route("{id:int=3}/OrderDetailById")]//约束int类型,且默认值为3
11     [HttpGet]//http://localhost:61218/api/TestRoute2/2/OrderDetailById
12     public IHttpActionResult GetById(int id){
13         return Ok<string>("Success" + id );
14     }
15     [Route("{no}/OrderDetailByNo")]
16     [HttpGet]//http://localhost:61218/api/TestRoute2/aa/OrderDetailByNo
17     public IHttpActionResult GetByNO(string no){
18         return Ok<string>("Success" + no);
19     }
20     [Route("{name}/OrderDetailByName")]
21     [HttpGet]//http://localhost:61218/api/TestRoute2/cc/OrderDetailByName
22     public IHttpActionResult GetByName(string name){
23         return Ok<string>("Success" + name);
24     }
25     [Route("postdata")]
26     [HttpPost]
27     public HttpResponseMessage PostData(int id){
28         return Request.CreateResponse();
29     }
30     [Route("Test/AttrRoute")]
31     [HttpPost]
32     public HttpResponseMessage SavaData(ORDER order){
33         return Request.CreateResponse();
34     }
35
  • PostData()和SavaData()的post请求
1 $http.post("http://localhost:61218/api/TestRoute2/postdata?id=1").then(res => {}, () => {})
2 $http.post("http://localhost:61218/api/TestRoute2/Test/AttrRoute",{data:{ID: 2, NO:"aaa"}}).then(res => {}, () => {}) 
原文地址:https://www.cnblogs.com/My-Sun-Shine/p/13509679.html