zoukankan      html  css  js  c++  java
  • ASP.NET WebApi 路由配置

    ASP.NET Web API路由是整个API的入口。我们访问某个资源就是通过路由映射找到对应资源的URL。通过URL来获取资源的。

    对于ASP.NET Web API内部实现来讲,我们的请求最终将定位到一个具体的Action上。所以说,ASP.NET Web API路由就是把客户端请求映射到对应的Action上的过程。

     路由分为两种模式:模板路由和特性路由。

    1.模板路由

    模板路由是ASP.NET Web API默认提供的路由。模板路由使用前需要定义路由模板。如下面默认的路由模板:

    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web.Http;
     namespace Supernova.Webapi
    {
        public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                // Web API 配置和服务
    
                // Web API 路由
                config.MapHttpAttributeRoutes();
    
                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );
            }
        }
    }

    我们可以看到此模板的URL格式是api/{controller}/{id}。api代表在资源前面要带上api目录,controller代表请求资源的控制器名称。id代表一条资源的id,id 是可选的。这种默认的模板是不带action的,所以它是以请求方式来区分资源的,我们必须在action上添加请求方式特性加以区分。

    我们添加一个测试控制器api:

    public class TestController : ApiController
        {
            public object Get1()
            {
                return "d1";
            }       
        }

    我们添加两个方法如下:

    public class TestController : ApiController
        {
            public object Get1()
            {
                return "d1";
            }
            public object Get2()
            {
                return "d2";
            }
        }

    错误信息:

    {"Message":"出现错误。","ExceptionMessage":"找到了与该请求匹配的多个操作: 
    类型 Supernova.Webapi.Controllers.TestController 的 Get1
    类型 
    Supernova.Webapi.Controllers.TestController 的 Get2
    ","ExceptionType":"System.InvalidOperationException","StackTrace":"
    System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext) 在
    System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) 在
    System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
    "}

    我们将代码改为如下:

    public class TestController : ApiController
        {
            public object Get1()
            {
                return "d1";
            }
            [HttpPost]
            public object Get2()
            {
                return "d2";
            }
        }

    调试返回Get1的信息。

    从上面两个测试我们可以得出如下结论:

    action的默认请求方式是HttpGet。
    当多个action的 请求方式一样的话,在默认路由模板下(没有action),将会匹配多个操作。
    基于上面两点结论,默认路由模板无法满足针对一种资源一种请求方式的多种操作(比如修改操作,可能针对不同的字段进行修改)。

    我们重新定制模板路由,如下:

    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web.Http;
     namespace Supernova.Webapi
    {
        public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                // Web API 配置和服务
    
                // Web API 路由
                config.MapHttpAttributeRoutes();
    
                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{action}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );
            }
        }
    }

    从上面我们可以看出,在默认路由的基础上,我们队路由模板增加了一级action。

    测试api如下:

     public class TestController : ApiController
        {
            public object Get1()
            {
                return "d1";
            }        
            public object Get2()
            {
                return "d2";
            }
        }

    我们再通过http://192.168.0.230/api/test访问,返回404。

    我们通过http://192.168.0.230/api/test/Get1访问,结果正确。

    我们通过http://192.168.0.230/api/test/Get2访问,结果正确。

    通过定制路由模板我们可以得出如下结论:
    通过在路由模板中增加action目录,对资源的定位直接作用到action上。
    多个HttpGet方法可以共存于一个controller中。
    基于上面两点结论,通过修改路由模板可以满足针对一种资源一种请求方式的多种操作。

    2.特性路由

    特性路由是通过给action打attribute的方式定义路由规则。

    有时候我们会有这样的需求,我们请求的一个资源带有子资源。比如文章评论这样有关联关系的资源。我们希望通过如下URL获得某篇文章下的所有评论:api/book/id/comments。而仅仅凭借模板路由很难实现这种路由模式。这时候我们就需要特性路由来解决这个问题了。ASP.NET Web API为我们准备了Route特性,该特性可以直接打到Action上,使用非常灵活、直观。

    我们重新定义api如下:

    public class TestController : ApiController
        {
           [Route("demo")]  
            [HttpGet]
            public object Get1()
            {
                return "d1";
            }
           [Route("demo/get")]
           [HttpGet]
            public object Get2()
            {
                return "d2";
            }
        }

    请求Get1的URL是http://192.168.0.230/demo

    请求Get2的URL是http://192.168.0.230/demo/get

    有时候我们想对某个资源的所有操作都加上一个统一的前缀:

    [RoutePrefix("api")]
        public class TestController : ApiController
        {
            [Route("demo")]  
            [HttpGet]
            public object Get1()
            {
                return "d1";
            }
           [Route("demo/get")]
           [HttpGet]
            public object Get2()
            {
                return "d2";
            }
        }

    如果我们还会有这样的需求,我的某个资源中的大部分请求都需要前缀,但是就是有那么一两个资源不需要加前缀:

     [RoutePrefix("api")]
        public class TestController : ApiController
        {
            [Route("~/demo")]  
            [HttpGet]
            public object Get1()
            {
                return "d1";
            }
           [Route("demo/get")]
           [HttpGet]
            public object Get2()
            {
                return "d2";
            }
        }

    现在问题又来了,那么多的请求,特别是Get请求方式,都需要带参数啊,怎么定义参数的类型,长度范围等约束条件呢?

    答案是可以通过"{参数变量名称:约束}"来约束路由中的参数变量。

    ASP.NET Web API内置约束包括:

    {x:alpha} 约束大小写英文字母
    {x:bool}
    {x:datetime}
    {x:decimal}
    {x:double}
    {x:float}
    {x:guid}
    {x:int}
    {x:length(6)}
    {x:length(1,20)} 约束长度范围
    {x:long}
    {x:maxlength(10)}
    {x:min(10)}
    {x:range(10,50)}
    {x:regex(正则表达式)}

    如下代码:

    [RoutePrefix("api")]
        public class TestController : ApiController
        {
            [Route("demo/{id:int}")]  
            [HttpGet]
            public object Get1()
            {
                return "d1";
            }
           [Route("demo/{name}")]
           [HttpGet]
            public object Get2()
            {
                return "d2";
            }
        }

    以上,如果片段变量id为int类型,就路由到第一个Action Get1,如果不是,路由到第二个Action Get2。

    可以为一个参数变量同时设置多个约束:

    [RoutePrefix("api")]
        public class TestController : ApiController
        {
            [Route("demo/{id:int:min(5)}")]  
            [HttpGet]
            public object Get1()
            {
                return "d1";
            }
           [Route("demo/{name}")]
           [HttpGet]
            public object Get2()
            {
                return "d2";
            }
        }

    请求URL:http://192.168.0.230/api/demo/1 定位到Get2

    参考资料:http://www.eggtwo.com/news/detail/155

  • 相关阅读:
    Android4.0 以后不允许在主线程进行网络连接
    关于升级linux下apache
    事物复制中大项目(Large Article)出问题如何快速修复
    国企银行面试总结
    Git命令详解(一)-个人使用
    函数体的规模要小,尽量控制在 50 行代码之内
    函数的功能要单一,不要设计多用途的函数
    在函数体的“出口处”,对 return 语句的正确性和效率进行检查
    在函数体的“入口处”,对参数的有效性进行检查
    有些场合用“引用传递”替换“值传 递”可以提高效率
  • 原文地址:https://www.cnblogs.com/zhengwk/p/5505127.html
Copyright © 2011-2022 走看看