25 | 路由与终结点:如何规划好你的Web API

自定义约束实现了路由约束接口,它只有一个 Match 方法,这个方法传入了 Http 当前的 httpContext,route,routeKey

这个 routeKey 就是我们要验证的 key 值

后面两个参数 RouteValueDictionary 就是当前可以获取到的这个 routeKey 对应的传入的值是什么值,这样就可以验证我们传入的信息

routeDirection 这个枚举的作用是当前验证是用来验证 URL 请求进来,验证是否路由匹配,还是用来生成 URL,是进还是出的这样一个定义,在不同的场景下面可能响应的逻辑是不一样的

下面的逻辑是如果路由是进来的,也就是通过 URL 配置 action 的情况,就做一个判断,根据 routeKey 取到当前输入的这个值,然后判断它是否可以转成 long,这个其实模拟了类型验证,比如说 long 型验证的方式

namespace RoutingDemo.Constraints
{public class MyRouteConstraint : IRouteConstraint{public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection){if (RouteDirection.IncomingRequest == routeDirection){var v = values[routeKey];if (long.TryParse(v.ToString(), out var value)){return true;}}return false;}}
}

RouteDirection

namespace Microsoft.AspNetCore.Routing
{public enum RouteDirection{IncomingRequest = 0,UrlGeneration = 1}
}

接下来看一下约束是如何注入到我们系统里生效的

可以给我们的约束起一个名字 isLong,这个名字就是用来 Attribute 上面标识约束的

services.AddRouting(options =>
{//options.ConstraintMap.Add("MyRouteConstraint", typeof(MyRouteConstraint));options.ConstraintMap.Add("isLong", typeof(MyRouteConstraint));
});

OrderController 里面也修改为 isLong

/// <summary>
///
/// </summary>
/// <param name="id">必须可以转为long</param>
/// <returns></returns>
//[HttpGet("{id:MyRouteConstraint}")]// 这里使用了自定义的约束
[HttpGet("{id:isLong}")]
//public bool OrderExist(object id)
public bool OrderExist([FromRoute] string id)
{return true;
}

启动程序,输入34,返回响应码200,输入abc,返回响应码404,也就是自定义约束生效了

接下来讲一下链接生成的过程

/// <summary>
///
/// </summary>
/// <param name="id">最大20</param>
/// <param name="linkGenerator"></param>
/// <returns></returns>
[HttpGet("{id:max(20)}")]// 这里使用了 Max 的约束
//public bool Max(long id)
public bool Max([FromRoute]long id, [FromServices]LinkGenerator linkGenerator)
{// 这两行就是分别获取完整 Uri 和 path 的代码// 它还有不同的重载,可以根据需要传入不同的路由的值var path = linkGenerator.GetPathByAction(HttpContext,action: "Reque",controller: "Order",values: new { name = "abc" });// 因为下面对 name 有一个必填的约束,所以这里需要传值var uri = linkGenerator.GetUriByAction(HttpContext,action: "Reque",controller: "Order",values: new { name = "abc" });return true;
}/// <summary>
///
/// </summary>
/// <param name="ss">必填</param>
/// <returns></returns>
[HttpGet("{name:required}")]// 必填约束
public bool Reque(string name)
{return true;
}

启动程序,端点调试,输入1,点击执行,可以看到

path 的值为

/api/Order/Reque/abc

uri 的值为

https://localhost:5001/api/Order/Reque/abc

在定义 Controller 的时候,实际上还会做一些接口废弃的过程,通过 [Obsolete]

/// <summary>
///
/// </summary>
/// <param name="ss">必填</param>
/// <returns></returns>
[HttpGet("{name:required}")]// 必填约束
[Obsolete]
public bool Reque(string name)
{return true;
}

我们不必直接删除我们的接口,它还可以正常工作,但是我们可以把它标记为已废弃,在 Swagger 上面会有体现

可以看到这个接口已经被标记为废弃的,但是它的调用还是可以工作的

总结一下

1、Restful 不是必须的,只要约束好 Http 方法以及 URL 地址,还有 Http 响应码,响应的 Json 格式,这些约定只要适合团队的协作习惯就可以了,也就是说需要定义好 API 的表达契约

2、建议是把 API 都约束在特定的目录下面,与其他功能性页面进行隔离,比如说 /api /api 加版本号这样子的方式

3、在废弃 API 的过程中间,应该是间隔版本的方式废弃,也就是说先将即将废弃的 API 标记为已废弃,但是它还是可以工作,间隔几个版本之后将代码删除掉

到目前为止,讲解了依赖注入,配置日志,中间件等必要的内容,下一节开始将进入微服务实战的部分

.NET Core开发实战(第25课:路由与终结点:如何规划好你的Web API)--学习笔记(下)...相关推荐

  1. .NET Core开发实战(第25课:路由与终结点:如何规划好你的Web API)--学习笔记(上)...

    25 | 路由与终结点:如何规划好你的Web API 路由系统在 ASP.NET MVC 框架里面就已经存在了,在 ASP.NET Core 框架里面进行了改进 路由系统的核心作用是指 URL 和 应 ...

  2. .NET Core开发实战(第5课:依赖注入:良好架构的起点)--学习笔记(上)

    05 | 依赖注入:良好架构的起点 为什么要使用依赖注入框架 借助依赖注入框架,我们可以轻松管理类之间的依赖,帮助我们在构建应用时遵循设计原则,确保代码的可维护性和可扩展性 ASP.NET Core ...

  3. .NET Core开发实战(定义API的最佳实践)Source Generators版

    前言 极客时间上的<.NET Core开发实战>是一门非常好的课程,作者肖伟宇在第31课(https://time.geekbang.org/course/detail/100044601 ...

  4. 笔记合并_.NET Core开发实战(第23课:静态文件中间件:前后端分离开发合并部署骚操作)学习笔记(上)...

    23 | 静态文件中间件:前后端分离开发合并部署骚操作 我们先来看一下静态文件中间件有哪些能力 1.支持指定相对路径 2.支持目录的浏览 3.支持设置默认文档 4.支持多目录映射 源码链接: http ...

  5. .NET Core开发实战(第23课:静态文件中间件:前后端分离开发合并部署骚操作)--学习笔记(上)...

    23 | 静态文件中间件:前后端分离开发合并部署骚操作 我们先来看一下静态文件中间件有哪些能力 1.支持指定相对路径 2.支持目录的浏览 3.支持设置默认文档 4.支持多目录映射 源码链接: http ...

  6. .NET Core开发实战(第26课:工程结构概览:定义应用分层及依赖关系)--学习笔记...

    26 | 工程结构概览:定义应用分层及依赖关系 从这一节开始进入微服务实战部分 这一节主要讲解工程的结构和应用的分层 在应用的分层这里定义了四个层次: 1.领域模型层 2.基础设施层 3.应用层 4. ...

  7. 2、SpringBoot接口Http协议开发实战8节课(7-8)

    7.SpringBoot2.x文件上传实战 简介:讲解HTML页面文件上传和后端处理实战 1.讲解springboot文件上传 MultipartFile file,源自SpringMVC 1)静态页 ...

  8. 微信小程序项目开发实战:用WePY、mpvue、Taro打造高效的小程序》(笔记4)支持React.js语法的Taro框架

    Taro的编写代码方式和mpvue.WePY框架最大的一个差别就是,Taro并不是基于Vue.js的语法规范,而是遵循React语法规范,它采用与React一致的组件化思想,组件生命周期与React保 ...

  9. 第2课第3节_Java面向对象编程_继承性_P【学习笔记】

    摘要:韦东山android视频学习笔记  面向对象程序的三大特性之继承性:继承性的主要作用就是复用代码.继承性也有一定的限制,如图一 图一 1.我们在第2课第2节_Java面向对象编程_封装性_P 中 ...

最新文章

  1. Linux环境编程--fflush(stdout)有什么作用
  2. SVN 问题解决之 The XML response contains invalid XML
  3. python开发好学吗-Python人工智能开发难学吗
  4. java和python的比较-java 和 python的一些对比
  5. benet 3.0的构建企业网络视频第二章地址
  6. 使用 GitHub, Jekyll 打造自己的免费独立博客
  7. C/C++ 动态存储分配 malloc calloc realloc函数的用法与区别
  8. WebService C#开发/调用
  9. mybatis学习(39):动态sql片段
  10. 不可不知的站群外推方法与技巧
  11. 同步I/O 和 异步I/O
  12. php工具箱mysql停止进程_PHP进程卡死和MySQL超时时间的设置方法
  13. html下拉框设置默认值_html 里select 下拉列表中设置默认值怎么写
  14. react在线浏览doc_如何把doc文件转换成PDF格式?教你一招秒实现
  15. 一台电脑如何同开两个或多个飞信?
  16. 使用react-pdf预览pdf
  17. 7.1 认识Access报表
  18. mysql减五元,[MySQL]處理字元編碼的一些心得
  19. 亲测可用~ Ubuntu20.04 findfont: Font family [‘sans-serif‘] not found. Times New Roman 字体缺失
  20. linux at24c 前几个字节错误,I2C操作笔记——以 AT24C04为例

热门文章

  1. C#隐藏桌面图标和任务栏
  2. [Java] java中的接口定义
  3. ArcEngine 没有Esri.ArcGis.GeoAnalyst 命名空间
  4. vlc传输_如何使用VLC通过网络流式传输视频和音乐
  5. 前端进阶之路: 前端架构设计(2)-流程核心
  6. centos 新建swap区文件
  7. fedora17的gnome3桌面美化
  8. LAMP攻略: LAMP环境搭建,Linux下Apache,MySQL,PHP安装与配置
  9. IP代理在网络游戏中的应用
  10. WPF DataGrid 如何将被选中行带到视野中