这里写自定义目录标题

  • 一、概述
  • 二、ControllerBase
    • 1、ControllerBase基类和Controller基类的关系
    • 2、ControllerBase基类和Controller基类的区别
    • 3、ControllerBase作用
  • 三、[ApiController]属性
    • 1、属性路由要求
    • 2、自动 HTTP 400 响应
    • 3、绑定源参数推理
    • 4、Multipart/form-data 请求推理
    • 5、错误状态代码的问题详细信息
    • 小结
  • 四、[RouteAttribute]属性
  • 五、解决上节遗留问题
  • 六 、总结

一、概述

书接上回,上节我们留了几个问题,即:

1、接口Hello的名字究竟怎么来的?

2、我们如果想把接口改成其他的名称,应该怎么做?

3、我们继承ControllerBase,以及[Route(“[controller]”)]属性,又是分别起到什么作用?

需要解决以上几个问题,我们就要继续深入研究Controller相关的一些东西,主要包括ControllerBase基类、ApiController 属性,我们想要精通某个技术,必须要了解器原理,才能做到触类旁通、灵活运用。

ControllerBase 是Web API 控制器的基类,换句话说,Web API 控制器通常都应继承 ControllerBase。做过MVC项目的朋友可能都知道,在MVC里面控制器一般继承Controller。两者有什么关系和区别吗?

二、ControllerBase

1、ControllerBase基类和Controller基类的关系

查看ControllerBase 的定义,这是一个抽象类;

再看Controller的定义,其继承了ControllerBase


两者的关系是:Controller基类派生自ControllerBase

2、ControllerBase基类和Controller基类的区别

Controller 派生自 ControllerBase,主要区别是Controller 功能更强大,主要添加对视图的支持,因此它用于处理 Web 页面,而不是 Web API 请求。 如果同一控制器需要同时支持视图和 Web API,那应该派生自 Controller。如果仅仅需要支持 Web API,那就派生自 ControllerBase即可,这样更加轻量级。

3、ControllerBase作用

ControllerBase 类主要作用是提供了很多用于处理 HTTP 请求的属性和方法。比如我们可以通过这个基类提供的Request属性获取请求头信息:

// 获取请求头
 var headers = this.Request.Headers; foreach (var kvp in headers) { Console.WriteLine($"{kvp.Key} : {kvp.Value}"); }

运行结果可以看到我们把请求头的全部信息都获取到了

有关ControllerBase 可用方法和属性的列表,具体不展开,可参考官方文档。

三、[ApiController]属性

作用:[ApiController] 属性应用于控制器类,让控制器上或该控制器下的的API具有以下几个固定的功能

(1)、属性路由要求
(2)、自动 HTTP 400 响应
(3)、绑定源参数推理
(4)、Multipart/form-data 请求推理
(5)、错误状态代码的问题详细信息
下面分别阐述

1、属性路由要求

先介绍 ASP.NET Core 中的路由的两种方式 传统路由属性路由

传统路由实现方式:

// 在Program.cs中或Startup.cs中使用
app.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id" />);

或者

// 在Program.cs中或Startup.cs中使用
app.MapDefaultControllerRoute();

属性路由的实现方式:

// 在Program.cs中或Startup.cs中使用
app.MapControllers();

然后在Controller中使用[Route(“”)]属性指定路由名称,如示例代码:

[ApiController][Route("[controller]")]public class WeatherForecastController : ControllerBase

介绍完了两种路由,再来看什是属性路由要求?

所谓属性路由要求,意思就是如果Controller加了[ApiController]属性,就必须走属性路由的方式。这也就能解释示例代码Controller上存在[ApiController][Route(“[controller]”)]这两个属性。

2、自动 HTTP 400 响应

什么是http 400?比如我们对用户注册的手机号码格式有校验要求,手机号码格式不正确时候,这个时候参数校验就会不通过,需要写如下代码。

if (!ModelState.IsValid){return BadRequest(ModelState);}

[ApiController] 属性使模型验证错误自动触发 HTTP 400 响应。 因此,操作方法中不需要上述代码。

3、绑定源参数推理

我们获取参数的时候,有以下一些绑定源:

[FromBody] 请求正文
[FromForm] 请求正文中的表单数据
[FromHeader] 请求标头
[FromQuery] 请求查询字符串参数
[FromRoute] 当前请求中的路由数据
[FromServices] 作为操作参数插入的请求服务
[AsParameters] 方法参数

[ApiController] 属性借助推理规则,无需手动识别绑定源。先大概描述下,后续在参数传递和绑定章节再详细展开这些规则。

4、Multipart/form-data 请求推理

[ApiController] 属性针对 IFormFile 和 IFormFileCollection 类型的操作。 为这些类型自动推断内容类型为: multipart/form-data。不需要人工在请求Header头上指定类型。

5、错误状态代码的问题详细信息

错误结果(状态代码>= 400)以ProblemDetails展示。
ProblemDetails的定义如下:

看怎么使用:
比如有如下的代码,抛出一个404 NotFound的异常

if (pagePath == null){return NotFound();}

NotFound 方法会生成带 ProblemDetails 正文的 HTTP 404 状态代码。 例如:

{type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",title: "Not Found",status: 404,traceId: "0HLHLH32KRN20:00000001"}

小结

以上5点就是[ApiController]属性起到的作用,接下来我们来介绍[RouteAttribute]属性的作用。

四、[RouteAttribute]属性

其实上面属性路由环节基本已经介绍了这个属性,这个属性的作用就是:指定控制器上的属性路由

包含三个属性:

Name :路由名称。

Order :路由执行的顺序。

Template :路由模板。 可为 null。

其中,最关键的Template ,一般通过Template指定接口的访问路径,比如:

[Route(“/route/norest/{name” />五、解决上节遗留问题

有了这些基础知识,我们来解决上节遗留的问题:

1、接口Hello的名字究竟怎么来的?

答:接口Hello的名字是根据下面代码有关

[Route("[controller]")] public class HelloController : ControllerBase

因为Controller的名称为Hello,根据restful API规范,Controller里面又只有一个Get请求的接口,故Action的定义没有影响到接口的最终名称。

2、我们如果想把接口改成其他的名称,应该怎么做?
答:修改成如下代码即可,比如改成Greeting

 [ApiController] [Route("")] public class HelloController : ControllerBase {[HttpGet("Greeting",Name = "GetHello")]public string Hello() {return "Hello,World!"; } }

有两处改动,去除Controller的Route名称,改为空字符串,然后给Hello方法指定Template(注:HttpGet可以直接指定Template )。

运行结果如下:

可以看到,名称已经修改成功。

3、我们继承ControllerBase,以及[Route(“[controller]”)]属性,又是分别起到什么作用?

答:这个上面都有详细描述了

六 、总结

本节的目标主要讲述controller相关的一些知识,再解决第1个问题的过程中,出现了一个restful API规范的概念,以及在路由环节的介绍基本也是带过,下节我们将深入路由环节,揭开它的神秘面纱。

敬请期待…