以前写过ASP.NET Core 2.x的REST API文章,今年再更新一下到3.0版本。

先决条件

我在B站有一个非常入门的ASP.NET Core 3.0的视频教程,如果您对ASP.NET Core不了解,就可以先看一下里面的基础知识和API相关的内容,地址是:https://www.bilibili.com/video/av65313713/

预备知识:ASP.NET Core 和 C#

工具:Visual Studio 2019最新版(VSCode、VS for Mac,Rider等也凑合),POSTMAN

Web API

Web API通常是指“使用HTTP协议并通过网络调用的API”,由于它使用了HTTP协议,所以需要通过URI信息来指定端点。

API是Application Programming Interface的缩写,是软件的外部接口。也就是说,针对某个软件,人们可以知道它的外部功能,但并不知道(也不需要知道)它的内部运作细节,为了从外部调用某些功能,需要指定软件的调用规范等信息,这样的规范就是API。

所以Web API就是一个Web系统,通过访问URI可以与其进行信息交互。

大多数的 Web API 并不是 RESTful API

REST一词是在2000年首次出现的,它是由Roy Fielding博士在《架构风格以及基于网路的软件架构设计》这篇论文中提到的。他为REST风格的API制定了一套约束规范或者叫架构风格。

所以准确的说,只有符合了Roy Fielding架构风格的Web API才能称作是RESTful API。但是在实际开发中,有时候也有不完全符合Roy Fielding架构风格的情形出现,针对这点我将会在稍后的文章中介绍。

MVC模式与RESTful API

本系列文章中我将使用ASP.NET Core 3.0 MVC 来构建 RESTful API。

MVC(Model-View-Controller)我认为是一种主要用来构建UI的架构模式。对于MVC模式其实有很多种解释存在,但是无论那种解释,它们都会强调松耦合和关注点分离(separation of concerns)。

也是由于这两点的存在,程序的可测试性会大大提高,程序各部分的可复用性也很高。

更多关于MVC的介绍,可以看一下微软的官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/overview?view=aspnetcore-3.0

注意:MVC不是一个完整的应用程序架构,我认为它主要是用在展示层。所以实现UI就是MVC的一部分工作。

如何把MVC映射到API

我认为API同样可以看作是UI,它就是为API消费者所提供的UI。

让我们把MVC的三部分分别对应到API:

  • Model,它负责处理程序数据的逻辑。这里的Model可以包含在当前级别获取从存储获取数据的逻辑。但是有一些Model不包含任何逻辑,例如API所使用的DTO(Data transfer objects),这类的Model会被串行化到响应的body里面。

  • View,它是程序里负责展示数据的那部分。在构建API的时候,View就是数据或资源的展示。现在通常使用JSON格式。

  • Controller,它负责View和Model之间的交互。包括处理用户输入,用API的术语来讲,和API交互的“用户”就是指API的消费者,这类用户通常是另一个程序,例如Angular的SPA程序。

下面看看MVC这三部分的依赖关系:

Controller和View依赖于Model,Controller依赖于View,这也是分离的一个好处。

换句话说,Controller会选取适当的View来展现给用户,并一同把用户请求的Model数据带回去。

当API消费者发出请求的时候,在Controller上面的Action将会被触发,Controller会把接收到的输入数据发送给负责业务处理逻辑或数据访问逻辑的那部分程序。然后Controller会把Model返回给View,这里的View就是资源的展示(通常是JSON格式)。

接下来我们就是用这套概念和ASP.NET Core 3.0 来创建RESTful API。

但是请注意,通过ASP.NET Core MVC或API模板建立出来的新项目,我们并不会直接得到RESTful(REST架构风格)的API。我们必须在这个基础上,自己构建RESTful的API,因为之前已经提到了,标准的RESTful API有很多约束和规范。

创建ASP.NET Core 3.0 Web API项目

打开VS2019,选择项目模板ASP.NET Core Web Application:

然后为项目和解决方案起名字,并选择所在目录:

然后选择ASP.NET Core的项目模板:

首先要选择ASP.NET Core 3.0。

这里我选择了API这个模板。在以前,我通常会选择Empty模板,因为其它模板通常包含很多我不需要的东西,但是ASP.NET Core 3.0的API模板还是比较干净的,可以接受。

最后,由于本课程中不需要使用HTTPS和Docker,所以把这两个东西都勾掉。

解剖 ASP.NET Core 3.0 API 模板项目

点击Create,项目就建立好了:

先看看 appsettings.json:

里面只有默认的Log配置以及允许的Hosts。

而appsettings.Development.json里面:

也只有关于Log的默认配置。

注意:您需要知道appsettings.json 和 appsettings.Development.json之间的关系,关于这点可以看我ASP.NET Core 3.0的入门视频教程,但是更简单的办法是看一下官方文档:在ASP.NET Core中使用多个环境

项目模板里还有两个类我们不需要,所以把它删掉,分别是WeatherForecastController和WeatherForecast:

Program.cs:

这里其实就是整个程序的入口,Main方法负责配置和运行整个Web程序。

由于这是一个Web项目,所以我们还需要一个宿主(Host),这个宿主就是由下面的CreateHostBuilder方法来负责创建的。该方法首先会创建出一个实现了IHostBuilder接口的类(HostBuilder)的实例,然后调用它的Build方法来创建宿主(类型为Host,实现了IHost接口),最后调用宿主上面的Run方法来运行程序。

我们暂时不修改这里面的代码,所以一切都会按照项目模板默认的配置进行,注意到下面的方法里我们使用到了Startup这个类:

所以我们来看看Startup类。

Startup.cs

在这个类的构造函数里:

我们看到IConfiguration被注入了,这样就允许我们使用配置信息了,例如appsettings.json里面的配置信息。

下面有一个ConfigureServices方法:

这个方法负责向服务容器里面注册服务,已注册的服务可以通过依赖注入的方式在整个应用程序的其它地方进行使用。这里的服务是一个比较广义的概念,它就是一个在整个程序中做一些通用性操作的组件。

这里面只有一句话:

在3.0之前的版本里,这里面应该写的是services.AddMvc();,实际上在ASP.NET Core 3.0里面这样写也是可以的。但是AddMvc()里面不仅仅包含用于构建API的服务,还包含很多其它服务,例如构建View视图和TagHelper相关的服务等。而AddControllers()方法只包含用于构建API的那些服务,例如Controller的支持、Model绑定、Data Annotation和格式化器等等。

最下面还有一个Configure方法:

这个方法使用到了在ConfigureServices方法里面注册和配置的服务,所以这个方法是在ConfigureServices方法之后被调用的。

Configure方法是用来指定ASP.NET Core Web程序是如何响应每一个HTTP请求的。换句话说,也就是我们在这里配置请求的管道,配置的方法就是在这里添加很多中间件(Configure方法里面每一个app.UseXxx就是添加一个中间件,可以查看中间件的官方文档来了解更多)。

在开发环境的时候,如果有异常发生,那么会展示出一个异常页面:

app.UseAuthorization(),它会为整个Web程序添加授权的能力。当你需要考虑API安全性的时候,这点就很重要了。通常授权配置是在ConfigureServices方法里完成的,而我现在没有对授权进行配置,但是app.UseAuthorization()仍然会允许API可以被匿名的访问。

其它这几句话:

这几句话都是用来指定如何把HTTP请求分配到特定的Controller Action上面的。也就是说这是关于路由的。

很重要的一点就是:每一个请求会按照代码的顺序穿越所有在这里添加的中间件。但是每一个中间件都有可能将请求短路,这样的话请求就不会进入下一个中间件了,而会按照原路返回。

所以,添加中间件的顺序非常重要。如果你把授权中间件放在了Controller的后边,那么即使需要授权,那么请求也会先到达Controller并执行里面的代码,这样的话授权就没有意义了。

修改项目启动配置

我喜欢使用控制台启动Web程序,这样可以很直观的看到Log信息。为达到这个目的,可以修改launchSettings.json文件:

修改后,在项目的Debug属性里也有体现:

由于我主要是使用POSTMAN来调用API,所以我不需要Launch Browser(启动浏览器)。

运行程序

可以看到程序可以正常运行,并且在控制台上有日志的输出。

添加数据存储功能

想要做RESTful API的话,我们还需要数据,这里我准备采用SQLite来作为数据存储,使用Entity Framework Core 作为 ORM来与数据库进行交互。针对Entity Framework Core 3.0 如何在ASP.NET Core 里面使用,官方有个很不错的教程

下面开始在项目里添加SQLite和EFCore 3.0(这部分官方文档可以点击这里)的支持:

  • 首先,需要在我们的项目里通过Nuget添加 Microsoft.EntityFrameworkCore.Sqlite 这个包。

  • 然后,还需要安装 Microsoft.EntityFrameworkCore.Tools 这个包,它是用来做迁移的,关于这个包的更多功能解释,可以查看官方文档

建立Entities

我们先把项目的需求想的简单一点,暂时我们就做一个公司和公司员工的维护,两个Entity,两个表。

公司(Company)的Entity:

为什么使用Guid作为主键的类型?

员工(Employee)的Entity:

还涉及到一个性别的枚举:

建立DbContext

建立一个文件夹DbContexts,在里面建立一个类名叫RoutineDbContext:

关于这个类的理解并不是本文的重点,想知道详细的解释可以查看这部分的官方文档

  • 这个类需要继承于DbContext,而DbContext需要 DbContextOptions 才能工作,所以我采用了构造函数接收参数的形式来接收 DbContextOptions。

  • 中间的两个DbSet属性就可以简单的理解为把Entity映射到了数据库中的一个表。

  • 最下面我重写了OnModelCreating 这个方法。在里面,我对两个Entity的某些属性做了一些限制。关于这部分的详细内容,也可以查看官方文档。在方法的最后,我显式的指明了两个Entity之间的关系为一对多关系,并指明了外键。其实按照约定,它们两个之间的一对多关系是默认已经成立的,无需我来指明。

添加种子数据

还是在RoutineDbContext这个类里的OnModelCreating方法里,我添加如下代码来为数据库添加种子数据:

这里只添加了Company数据。

建立Repository

如果只是用来讲解RESTful API的话,不使用Repository等Service也行,就是直接在Controller里面使用DbContext也可以接受。但是我还是简单的写一个Repository吧(这个Repository并不是很规范),否则重复代码可能比较多。

首相看一下ICompanyRepository,也就是Repository的接口合约:

里面的功能我相信大家应该能看明白吧。

然后看一下实现,CompanyRepository:

比较长。。。

注册服务

在Startup的ConfigureServices方法里把DbContext和Repository注册到容器里:

关于这部分的知识,可以看官方文档:服务生命周期配置DbContext

修改Program

为了演示方便,我让数据库在每次程序启动的时候都会被删掉并重新进行迁移,同时设置好种子数据。这部分内容可查看迁移的官方文档创建删除API的官方文档

这里只修改了Main方法:

添加迁移

打开VS2019的Package Manager Console,并输入类似以下的命令来添加迁移:

命令执行成功后,会生成一个Migrations文件夹:

里面包含着这个这次的迁移类和当前模型的快照。

运行程序

可以看到执行了一些SQL语句,并且出现的Log都是绿色的Info,这说明数据库已经建立成功了。

看一下项目文件:

可以看到数据库已经成功的被建立了。

打开数据库:

可以看到种子数据已经成功写入。

使用ASP.NET Core 3.x 构建 RESTful API - 1.准备工作的更多相关文章

  1. 使用ASP.NET Core 3.x 构建 RESTful API - 2. 什么是RESTful API

    1. 使用ASP.NET Core 3.x 构建 RESTful API - 1.准备工作 什么是REST REST一词最早是在2000年,由Roy Fielding在他的博士论文<Archit ...

  2. 使用ASP.NET Core 3.x 构建 RESTful API - 3.4 内容协商

    现在,当谈论起 RESTful Web API 的时候,人们总会想到 JSON.但是实际上,JSON 和 RESTful API 没有半毛钱关系,只不过 JSON 恰好是RESTful API 结果的 ...

  3. 使用ASP.NET Core 3.x 构建 RESTful API - 4.2 过滤和搜索

    向Web API传递参数 数据可以通过多种方式来传给API. Binding Source Attributes 会告诉 Model 的绑定引擎从哪里找到绑定源. 共有以下六种 Binding Sou ...

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

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

  5. 使用ASP.NET Core 3.x 构建 RESTful API - 3.3 状态码、错误/故障、ProblemDetails

    HTTP状态码 HTTP状态码会告诉API的消费者以下事情: 请求是否执行成功了 如果请求失败了,那么谁为它负责 HTTP的状态码有很多,但是Web API不一定需要支持所有的状态码.HTTP状态码一 ...

  6. 使用ASP.NET Core 3.x 构建 RESTful API - 5.1 输入验证

    说到验证,那就需要做三件事: 定义验证规则 按验证规则进行检查 报告验证的错误.在把错误报告给API消费者的时候,报告里并不包含到底是服务端还是API消费者引起的错误,这是状态码的工作.而通常响应的B ...

  7. 使用ASP.NET Core 3.x 构建 RESTful API - 3.1 资源命名

    之前讲了RESTful API的统一资源接口这个约束,里面提到了资源是通过URI来进行识别的,每个资源都有自己的URI.URI里还涉及到资源的名称,而针对资源的名称却没有一个标准来进行规范,但是业界还 ...

  8. 使用ASP.NET Core 3.x 构建 RESTful API - 4.1 面向外部的Model

    Entity Framework Core 使用的 Entity Model 是用来表示数据库里面的记录的. 而面向外部的 model 则表示了要传输的东西.这类 model 有时候叫做 Dto,有时 ...

  9. 使用ASP.NET Core 3.x 构建 RESTful API - 4.3 HTTP 方法的安全性和幂等性

    什么样的HTTP方法是安全的? 如果一个方法不会该表资源的表述,那么这个方法就被认为是安全的. 例如 HTTP GET 和 HTTP HEAD 就被认为是安全的,但需要注意的是,这并不意味着执行GET ...

随机推荐

  1. Case1-basic network framework/Related organization‘s name

    常见的计算机网络物理拓扑结构: 1.星型网 2.树型网 3.分布式网络 4.总线型网 5.环型网 6.复合型网络 计算机网络相关的标准化组织: 国际标准化组织(ISO):International O ...

  2. 项目一:ssm超市订单管理系统

    声明:项目参考于课程教材,学习使用,仅在此记录 项目介绍 ssm超市订单管理系统,功能模块有订单管理,供应商管理,用户管理,密码修改,退出系统,管理模块中包括基本的增删改查 集成工具使用idea,基于 ...

  3. 原生js动态添加新元素、删除元素方法

    1. 添加新元素 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...

  4. 【NOIP2003】传染病控制

    Description 问题背景: 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府 决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种 ...

  5. [JOJZ]3855.选择困难症

    [问题描述]又到吃饭时间,Polo 面对饭堂里琳(fei)琅(chang)满(keng)目(die)的各种食品,又陷入了痛苦的抉择中:该是吃手(jiao)打肉饼好呢,还是吃豆(cai)角(chong) ...

  6. 并发新构件之DelayQueue:延时队列

    DelayQueue:延时队列,首先是一个队列,所以可以持有对象,但是仅限于实现了Delayed接口的对象.重写getDelay()和compareTo()(因为要比较)方法: 通俗来讲:延时队列的就 ...

  7. MySQL 5.7安装最佳实践

    MySQL 5.7安装最佳实践 1.环境准备OS: CentOS Linux release 7.4.1708 (Core) for VMwareMySQL: mysql-5.7.24-linux-g ...

  8. 可能是把 ZooKeeper 概念讲的最清楚的一篇文章

    转载自:https://github.com/Snailclimb/JavaGuide/blob/master/%E4%B8%BB%E6%B5%81%E6%A1%86%E6%9E%B6/ZooKeep ...

  9. 【Spring Cloud】客户端负载均衡组件——Ribbon(三)

    一.负载均衡 负载均衡技术是提高系统可用性.缓解网络压力和处理能力扩容的重要手段之一. 负载均衡可以分为服务器负载均衡和客户端负载均衡,服务器负载均衡由服务器实现,客户端只需正常访问:客户端负载均衡技 ...

  10. json::rapidjson工具

    源码地址: https://github.com/Tencent/rapidjson 可跨平台使用.将 rapidjson-master\include\rapidjson 中的 rapidjson ...