前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用ASP.NET Core 3.x 构建 RESTful API - 3.2 路由和HTTP方法

使用ASP.NET Core 3.x 构建 RESTful API - 3.2 路由和HTTP方法

作者头像
solenovex
发布2019-11-26 22:48:52
1.2K0
发布2019-11-26 22:48:52
举报
文章被收录于专栏:草根专栏草根专栏

ASP.NET Core 3.x 的路由

路由机制会把一个请求的URI映射到一个Controller上面的Action,所以当你发送一个HTTP请求的时候,MVC框架会解析这个请求的URI,并尝试着把它映射到一个Controller上面的Action。

两个路由中间件

在ASP.NET Core 3.x里面,建议使用Endpoint路由来进行设置。但是我们需要先在请求的管道里面添加两个中间件:

  • app.UseRouting()。它是用来标记路由决策在请求管道里发生的位置,也就是在这里会选择端点。
  • app.UseEndpoints()。它是用来标记选择好的端点在请求管道的什么地方来执行。

这样做的好处就是,我们可以在选择端点和执行端点的中间位置插入其它的中间件。这样的话,插入到中间位置的中间件就会知道哪个端点被选取了,而且它也有可能会选择其它的端点。

一个非常好的例子就是授权中间件:

app . UseRouting( ) ; 
app . UseAuthorization( ) ; 
app . UseEndpoints( endpoints 
endpoints .MapControllers( ) ;
app . UseRouting( ) ; app . UseAuthorization( ) ; app . UseEndpoints( endpoints endpoints .MapControllers( ) ;

如果授权成功,那么就继续执行到之前选定的端点,否则的话就会跳转到其它端点或者短路返回。

官方文档:Startup里面路由配置的官方文档

映射端点

还是可以有两种方式进行设置:基于约定 或者 基于属性。

基于约定的路由,例如这两种:

app . UseEndpoints( endpoints 
endpoints . MapControllerRoute( 
"default", 
name : 
" {controller=Home} ) ; 
pattern: 
endpoints .MapRazorPages( ) ;
app . UseEndpoints( endpoints endpoints . MapControllerRoute( "default", name : " {controller=Home} ) ; pattern: endpoints .MapRazorPages( ) ;

这种方式更适合于服务器端的Web应用程序。

而针对Web API,使用基于属性的路由更加适合:

app . UseEndpoints( endpoints 
endpoints .MapControllers( ) ;
app . UseEndpoints( endpoints endpoints .MapControllers( ) ;

可以看到,这里面仅仅映射了Controller,并没有使用任何约定,所以我们需要采用属性(Attribute)来进行设定。这里需要用到属性(attribute)和URI模板。

  • 属性(Attribute)。例如[Route],[HttpGet],[HttpPost]等等,可以把它们放在Controller级别,也可以放在Action级别上。
  • URI模板。将属性结合URI模板一起使用,就可以把请求映射到Controller的Action上面。

例如:

ApiController] 
Route( template: "api/companies " ) ] 
I reference 
public class CompaniesController 
ControllerBase 
private readonly ICompanyRepository 
companyRepos i tory ; 
O references 
public CompaniesController(ICompanyRepository companyRepository) 
HttpGet 
O references 
public async Task<IActionResult> GetCompanies() 
await companyRepository .GetCompaniesAsync() ; 
var companies = 
return new JsonResult(companies);
ApiController] Route( template: "api/companies " ) ] I reference public class CompaniesController ControllerBase private readonly ICompanyRepository companyRepos i tory ; O references public CompaniesController(ICompanyRepository companyRepository) HttpGet O references public async Task<IActionResult> GetCompanies() await companyRepository .GetCompaniesAsync() ; var companies = return new JsonResult(companies);

官方文档:路由基础知识

HTTP 方法

不同的动作可以作用于相同的资源URI,例如获取一个公司(api/company/3)和删除一个公司(api/company/3)的URI就是一样的。但是它们的HTTP方法则不同,一个是GET,一个是DELETE。下面我们就来看看那些动作应该对应哪些 HTTP 方法。

POST

需求:添加一个公司信息。

需求图解:

添 加 
, 加 好 的 
公 司 信 , 
公 司 信 , 
公 司 资 源
添 加 , 加 好 的 公 司 信 , 公 司 信 , 公 司 资 源

HTTP请求图解:

POST api/companies 
POST 对 应 的 操 作 
就 是 建 立 资 源 
POST 的 参 数 放 在 
请 求 的 body 里 面 
POST 
ompany 信 息 
在 body 里 
pi/companies/{ 生 成 的 id} 
的 内 容 
POST 请 求 应 该 返 回 新 创 建 的 资 源 
以 及 可 以 获 取 该 资 源 的 唯 一 标 识 U 剛 
api/Compan ies
POST api/companies POST 对 应 的 操 作 就 是 建 立 资 源 POST 的 参 数 放 在 请 求 的 body 里 面 POST ompany 信 息 在 body 里 pi/companies/{ 生 成 的 id} 的 内 容 POST 请 求 应 该 返 回 新 创 建 的 资 源 以 及 可 以 获 取 该 资 源 的 唯 一 标 识 U 剛 api/Compan ies

文字解释:

添加公司这个需求的HTTP表示就是 POST api/companies。

当我们向 api/companies这个标示添加一个公司信息的时候,就会利用提供的公司信息创建一个公司的资源。这里对应的HTTP方法是POST。

POST请求的参数通常存放在请求的body里面,所以公司的信息就放在了body里面。

当公司资源创建好之后,这个action应该返回新创建的资源以及可以获取该资源的路径标识,也就是api/companies/{新资源的id}。

GET

获取单个资源

需求:获取一个公司信息

需求图解:

获 取 
公 司 信 
公 司 资 源
获 取 公 司 信 公 司 资 源

HTTP请求图解:

GET api/companies/{compayld} 
GET 对 应 的 动 作 就 是 
获 取 资 源 
G ET 
GET 请 求 会 返 回 请 求 路 径 所 对 应 的 资 源 
pi/companies/{companyld} 
的 内 容 
不 需 要 参 数 
api ℃ ompanies/{companyld} 
通 过 这 种 形 式 (URI) 来 表 示 公 司 资 源 中 的 一 个 公 司
GET api/companies/{compayld} GET 对 应 的 动 作 就 是 获 取 资 源 G ET GET 请 求 会 返 回 请 求 路 径 所 对 应 的 资 源 pi/companies/{companyld} 的 内 容 不 需 要 参 数 api ℃ ompanies/{companyld} 通 过 这 种 形 式 (URI) 来 表 示 公 司 资 源 中 的 一 个 公 司

文字解释:

我们想要通过 api/companies/{companyId} 这个标示来获取一个公司资源,这里就需要使用HTTP GET 方法,放在一起就是 GET api/companies/{companyId}。

GET请求总是会返回请求 URI 所对应的资源,所以这个请求会返回这个资源的内容。

获取集合资源

需求:获取符合查询条件的公司资源

需求图解:

获 取 
符 合 条 件 的 
公 司 信 息 
查 询 条 件 
公 司 资 源
获 取 符 合 条 件 的 公 司 信 息 查 询 条 件 公 司 资 源

HTTP请求图解:

GET api/companies?param1=xx&param2=xx... 
GET 对 应 的 动 作 就 是 
获 取 资 源 
GET 
GET 请 求 会 返 回 请 求 路 径 所 对 应 的 资 源 
pi/companies/{companyldl} 
api/companies/{companyldn} 
的 内 容 
自 定 义 的 
查 询 参 
G ET 的 参 数 是 资 源 地 址 ? 后 边 的 部 分 , 
例 如 GET api/companies?name=Nick 
api.Com pan ies
GET api/companies?param1=xx&param2=xx... GET 对 应 的 动 作 就 是 获 取 资 源 GET GET 请 求 会 返 回 请 求 路 径 所 对 应 的 资 源 pi/companies/{companyldl} api/companies/{companyldn} 的 内 容 自 定 义 的 查 询 参 G ET 的 参 数 是 资 源 地 址 ? 后 边 的 部 分 , 例 如 GET api/companies?name=Nick api.Com pan ies

这个需求是按条件搜索资源,可能返回0个或者多个符合条件的资源。这里我们使用HTTP的GET方法,如果想获取所有的公司资源,那么请求路径是 api/companies;如果想获取符合查询条件的公司资源,那么请求里就需要一些参数,通常使用查询字符串(query string)来传递参数,例如:

GET api/someresources?param1=value1&param2=value2

GET api/products?xxxxx=something

在这里,参数是在问号?后边,以name=value的形式存在。如果有多个查询参数,它们之间使用 & 符号分隔开。

当搜索资源的工作结束后,GET请求会返回匹配该路径(包括参数部分)的资源。

DELETE

需求:删除一个公司

需求图解:

删 除 
公 司 资 源
删 除 公 司 资 源

HTTP请求图解:

DELETE api/companies/{companyld} 
G ET 
DELETE 会 
删 除 路 径 所 对 应 的 资 源 
没 有 返 回 
没 有 参 数 
api ℃ ompanies/{companyld} 
通 过 这 种 形 式 (URI) 来 表 示 公 司 资 源 中 的 一 个 公 司
DELETE api/companies/{companyld} G ET DELETE 会 删 除 路 径 所 对 应 的 资 源 没 有 返 回 没 有 参 数 api ℃ ompanies/{companyld} 通 过 这 种 形 式 (URI) 来 表 示 公 司 资 源 中 的 一 个 公 司

文字解释:

HTTP 的 DELETE 方法就很好理解了,就是删除指定路径的资源而已,而且不需要返回任何东西。

PATCH

需求:更新公司的信息。

需求图解:

公 司 信 息 
公 司 资 源
公 司 信 息 公 司 资 源

HTTP请求图解:

РАТСН api/companies/{companyld} 
РАТСН 
РАТСН 
/lEfZ,a 
РАТСН$]ЗИ 
api/companies/{companyld}
РАТСН api/companies/{companyld} РАТСН РАТСН /lEfZ,a РАТСН$]ЗИ api/companies/{companyld}

文字解释:

这里有些初学者可能会出错。HTTP 用来表示更新信息的方法是 PATCH,所以整个请求时 PATCH api/companies/{companyId}。注意PATCH表示对资源进行局部更新。

和POST一样,PATCH的参数也位于请求的body里面。例如,如果你想更新公司的名称,那么就要把新的公司名称放在body里面。

PATCH的请求无需返回任何东西。

PUT

需求:替换公司信息。

需求图解:

替 换 
公 司 信 息 
公 司 资 源
替 换 公 司 信 息 公 司 资 源

HTTP请求图解:

PUT api/companies/{compayld} 
PUT 会 完 全 替 换 资 源 
PUT 
公 司 信 息 
在 body 里 
PUT 的 参 数 在 
请 求 的 body 里 
可 选 : 如 果 资 源 原 本 不 存 在 , 那 么 就 创 建 资 源 。 
这 种 情 况 下 就 应 该 返 回 新 创 建 的 资 源 。 
如 果 资 源 原 来 存 在 , 就 进 行 替 换 操 作 , 
那 么 就 无 需 返 回 任 何 东 西 。 
•api/companies/{companyld} 
的 内 容 
api/companies/{companyld} 
通 过 这 种 形 式 (URI) 来 表 示 公 司 资 源 中 的 一 个 公 司
PUT api/companies/{compayld} PUT 会 完 全 替 换 资 源 PUT 公 司 信 息 在 body 里 PUT 的 参 数 在 请 求 的 body 里 可 选 : 如 果 资 源 原 本 不 存 在 , 那 么 就 创 建 资 源 。 这 种 情 况 下 就 应 该 返 回 新 创 建 的 资 源 。 如 果 资 源 原 来 存 在 , 就 进 行 替 换 操 作 , 那 么 就 无 需 返 回 任 何 东 西 。 •api/companies/{companyld} 的 内 容 api/companies/{companyld} 通 过 这 种 形 式 (URI) 来 表 示 公 司 资 源 中 的 一 个 公 司

文字解释:

HTTP 的 PUT 方法用于完全替换已存在的一个资源;或者如果标识URI对应的资源不存在,那么就创建一个资源。对于后一种情况,它的效果和添加操作是一样的。

和 POST 一样,PUT的参数也位于请求的body里面。

如果是替换现有资源,那么无需返回任何东西;但如果是创建资源的操作,就应该返回新创建的资源。

综上

通过HTTP方法可进行的CRUD基本操作已经介绍的差不多了,但是这里的CRUD只是从API消费者的角度而言。例如,DELETE api/companies/12 并不意味着id为12的公司信息从数据库中被删除了,也许只是把该公司的信息的状态设置为deleted而已。

对于不限于CRUD的其它操作,我们也得使用这些HTTP方法来进行表示,多少要进行一些妥协。

最后使用一张图表总结一下这些HTTP方法对应的操作:

实际上还有 HTTP 的 OPTIONS 和 HEAD 也会直接或者间接的用到,这俩以后再说吧。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-11-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ASP.NET Core 3.x 的路由
  • HTTP 方法
    • POST
      • GET
        • 获取单个资源
        • 获取集合资源
      • DELETE
        • PATCH
          • PUT
            • 综上
            相关产品与服务
            消息队列 TDMQ
            消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档