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":"找到了与该请求匹配的多个操作: \r\n类型 Supernova.Webapi.Controllers.TestController 的 Get1\r\n类型
Supernova.Webapi.Controllers.TestController 的 Get2","ExceptionType":"System.InvalidOperationException","StackTrace":" 在
System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)\r\n 在
System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)\r\n 在
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()}
{x:length(,)} 约束长度范围
{x:long}
{x:maxlength()}
{x:min()}
{x:range(,)}
{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
ASP.NET WebApi 路由配置的更多相关文章
- ASP.NET WebApi 路由配置【转】
一.路由介绍 ASP.NET Web API路由是整个API的入口.我们访问某个资源就是通过路由映射找到对应资源的URL.通过URL来获取资源的. 对于ASP.NET Web API内部实现来讲,我们 ...
- 史上最全的ASP.NET MVC路由配置
MVC将一个Web应用分解为:Model.View和Controller.ASP.NET MVC框架提供了一个可以代替ASP.NETWebForm的基于MVC设计模式的应用. AD:51CTO 网+ ...
- ASP.NET MVC路由配置(转载自http://www.cnblogs.com/zeusro/p/RouteConfig.html )
把apress.pro.asp.net.mvc.4.framework里的CHAPTER 13翻译过来罢了. XD 首先说URL的构造. 其实这个也谈不上构造,只是语法特性吧. 命名参数规范+匿名对象 ...
- 史上最全的ASP.NET MVC路由配置,以后RouteConfig再弄不懂神仙都难救你啦~
继续延续坑爹标题系列.其实只是把apress.pro.asp.net.mvc.4.framework里的CHAPTER 13翻译过来罢了,当做自己总结吧.内容看看就好,排版就不要吐槽了,反正我知道你也 ...
- Asp.Net Webapi路由基本设置
1.直接在Global.asax中添加配置 如: using MvcApplication4.App_Start; using System; using System.Collections.Gen ...
- asp.net MVC路由配置总结
URL构造 命名参数规范+匿名对象 routes.MapRoute(name: "Default",url: "{controller}/{action}/{id}&qu ...
- ASP.NET MVC路由配置
一.命名参数规范+匿名对象 routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}" ...
- (转)ASP.NET MVC路由配置
一.命名参数规范+匿名对象 1 routes.MapRoute(name: "Default", 2 url: "{controller}/{action}/{id}&q ...
- ASP.NET WebAPI 路由规则与POST数据 【转】
http://www.cnblogs.com/liulun/archive/2012/06/20/2556556.html 蛋疼的路由规则约定 在上一篇文章中 我们成功通过AJAX获取到了服务器的数据 ...
随机推荐
- 3dmax 法线重置
从一个模型分离部位时,分离出的部分,面法线发生了混乱,左边原始模型,右边分离后 重置法线方法 对模型(比如对分离出的下半身)添加 EditoNormal修改器 选中模型部位 添加Edit Normal ...
- python dict操作
d1 = {'one': 1, 'two': 2} d2 = {'one': 1, 'two': 2} d3 = {'one': 1, 'two': 2} print(dir(d1)) # 1.con ...
- [NOIP2012] 摆花
1270. [NOIP2012] 摆花 http://cogs.pro/cogs/problem/problem.php?pid=1270 ★ 输入文件:flower.in 输出文件:flow ...
- Spring Boot Dubbo 构建分布式服务
概述: 节点角色说明 节点 角色说明 Provider 暴露服务的服务提供方 Consumer 调用远程服务的服务消费方 Registry 服务注册与发现的注册中心 Monitor 统计服务的调用次数 ...
- NOIp2013 火柴排队【逆序对/思维】 By cellur925
题目大意:给你两列数\(ai\)和\(bi\),你可以交换每列数中相邻的两个数,求一个最小交换次数使\(\sum_{i=1}^{n}(a_i-b_i)^2\) 最小. 最后满足条件的两个序列一定是各个 ...
- Python-10-条件和条件语句
num = int(input('Enter a number: ')) if num > 0: print('The number is positive') elif num < ...
- 网站前端开发--css篇
Ⅰ 全局:global.css 全局样式为全站公用,为页面样式基础,页面中必须包含. 结构:layout.css 页面结构类型复杂,并且公用类型较多时使用.多用在首页级页面和产品类页面中. 私有:st ...
- 2017EIS高校运维大赛ctf wirteup
php代码审计 题目很简单GET传入参数args然后eval(var_dump($$args))直接传入全局变量GLOBALS就能执行 php是最好的语言 .bak泄露拿到源码 <?php $v ...
- 【BZOJ2428】均分数据
题解 先说说黄学长的做法: 当温度比较高的时候,贪心 每次随机一个数,把他放进当前和最少的那一组里面 温度足够低的时候就完全随机然后转移 对于一个排列,分组强制连续 答案显然唯一,做一遍(dp)就好 ...
- Codeforces Round #563 (Div. 2) A. Ehab Fails to Be Thanos
链接:https://codeforces.com/contest/1174/problem/A 题意: You're given an array aa of length 2n2n. Is it ...