之前写过ASP.NET Core 2.x的REST API文章,今年再更新一下到3.0版本。web
我在B站有一个很是入门的ASP.NET Core 3.0的视频教程,若是您对ASP.NET Core不了解,就能够先看一下里面的基础知识和API相关的内容,地址是:https://www.bilibili.com/video/av65313713/。shell
预备知识:ASP.NET Core 和 C# 数据库
工具:Visual Studio 2019最新版(VSCode、VS for Mac,Rider等也凑合),POSTMAN json
Web API一般是指“使用HTTP协议并经过网络调用的API”,因为它使用了HTTP协议,因此须要经过URI信息来指定端点。 浏览器
API是Application Programming Interface的缩写,是软件的外部接口。也就是说,针对某个软件,人们能够知道它的外部功能,但并不知道(也不须要知道)它的内部运做细节,为了从外部调用某些功能,须要指定软件的调用规范等信息,这样的规范就是API。 安全
因此Web API就是一个Web系统,经过访问URI能够与其进行信息交互。 网络
REST一词是在2000年首次出现的,它是由Roy Fielding博士在《架构风格以及基于网路的软件架构设计》这篇论文中提到的。他为REST风格的API制定了一套约束规范或者叫架构风格。 架构
因此准确的说,只有符合了Roy Fielding架构风格的Web API才能称做是RESTful API。可是在实际开发中,有时候也有不彻底符合Roy Fielding架构风格的情形出现,针对这点我将会在稍后的文章中介绍。 mvc
本系列文章中我将使用ASP.NET Core 3.0 MVC 来构建 RESTful API。 app
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的一部分工做。
我认为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有不少约束和规范。
打开VS2019,选择项目模板ASP.NET Core Web Application:
而后为项目和解决方案起名字,并选择所在目录:
而后选择ASP.NET Core的项目模板:
首先要选择ASP.NET Core 3.0。
这里我选择了API这个模板。在之前,我一般会选择Empty模板,由于其它模板一般包含不少我不须要的东西,可是ASP.NET Core 3.0的API模板仍是比较干净的,能够接受。
最后,因为本课程中不须要使用HTTPS和Docker,因此把这两个东西都勾掉。
点击Create,项目就创建好了:
先看看 appsettings.json:
里面只有默认的Log配置以及容许的Hosts。
而appsettings.Development.json里面:
也只有关于Log的默认配置。
注意:您须要知道appsettings.json 和 appsettings.Development.json之间的关系,关于这点能够看我ASP.NET Core 3.0的入门视频教程,可是更简单的办法是看一下官方文档:在ASP.NET Core中使用多个环境。
项目模板里还有两个类咱们不须要,因此把它删掉,分别是WeatherForecastController和WeatherForecast:
这里其实就是整个程序的入口,Main方法负责配置和运行整个Web程序。
因为这是一个Web项目,因此咱们还须要一个宿主(Host),这个宿主就是由下面的CreateHostBuilder方法来负责建立的。该方法首先会建立出一个实现了IHostBuilder接口的类(HostBuilder)的实例,而后调用它的Build方法来建立宿主(类型为Host,实现了IHost接口),最后调用宿主上面的Run方法来运行程序。
咱们暂时不修改这里面的代码,因此一切都会按照项目模板默认的配置进行,注意到下面的方法里咱们使用到了Startup这个类:
因此咱们来看看Startup类。
在这个类的构造函数里:
咱们看到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 这个包,它是用来作迁移的,关于这个包的更多功能解释,能够查看官方文档。
咱们先把项目的需求想的简单一点,暂时咱们就作一个公司和公司员工的维护,两个Entity,两个表。
公司(Company)的Entity:
为何使用Guid做为主键的类型?
员工(Employee)的Entity:
还涉及到一个性别的枚举:
创建一个文件夹DbContexts,在里面创建一个类名叫RoutineDbContext:
关于这个类的理解并非本文的重点,想知道详细的解释能够查看这部分的官方文档。
这个类须要继承于DbContext,而DbContext须要 DbContextOptions 才能工做,因此我采用了构造函数接收参数的形式来接收 DbContextOptions。
中间的两个DbSet属性就能够简单的理解为把Entity映射到了数据库中的一个表。
最下面我重写了OnModelCreating 这个方法。在里面,我对两个Entity的某些属性作了一些限制。关于这部分的详细内容,也能够查看官方文档。在方法的最后,我显式的指明了两个Entity之间的关系为一对多关系,并指明了外键。其实按照约定,它们两个之间的一对多关系是默认已经成立的,无需我来指明。
仍是在RoutineDbContext这个类里的OnModelCreating方法里,我添加以下代码来为数据库添加种子数据:
这里只添加了Company数据。
若是只是用来说解RESTful API的话,不使用Repository等Service也行,就是直接在Controller里面使用DbContext也能够接受。可是我仍是简单的写一个Repository吧(这个Repository并非很规范),不然重复代码可能比较多。
首先看一下ICompanyRepository,也就是Repository的接口合约:
里面的功能我相信你们应该能看明白吧。
而后看一下实现,CompanyRepository:
比较长。。。
在Startup的ConfigureServices方法里把DbContext和Repository注册到容器里:
关于这部分的知识,能够看官方文档:服务生命周期和配置DbContext。
为了演示方便,我让数据库在每次程序启动的时候都会被删掉并从新进行迁移,同时设置好种子数据。这部份内容可查看迁移的官方文档和建立删除API的官方文档。
这里只修改了Main方法:
打开VS2019的Package Manager Console,并输入相似如下的命令来添加迁移:
命令执行成功后,会生成一个Migrations文件夹:
里面包含着这个此次的迁移类和当前模型的快照。
能够看到执行了一些SQL语句,而且出现的Log都是绿色的Info,这说明数据库已经创建成功了。
看一下项目文件:
能够看到数据库已经成功的被创建了。
打开数据库:
能够看到种子数据已经成功写入。