- A+
ASP.NET Core Web API 教程
本系列文章主要参考了《Ultimate ASP.NET Core 3 Web API》一书,我对原文进行了翻译,同时适当删减、修改了一部分内容。
对于某些概念和原理,原书和本文中都没有进行详细描述,如果一一详细介绍,内容就显得臃肿且混乱,我个人是先对原书进行了通读,理解主要内容,然后再具体搜索了解其中不明白或者感兴趣的概念和知识点。
由于我的技术水平和英文水平都有限,且主要是为了方便以后自己查看回顾,所以有错误之处,还请各位批评指正。
第一章 项目配置
本章内容简介:Configuration 在开发过程中至关重要,我们首先需要了解如何配置我们的应用程序。在之前的 .NET Framework 项目中,我们一般是通过 web.config 文件来完成对应用程序的配置,而在 .NET Core 中,我们不再使用该文件,而是使用 .NET Core 内置的 Configuration 框架。本文将介绍 Startup 类中的配置方法以及如何通过这些方法来设置应用程序。除此之外,还将介绍如何注册服务以及如何通过扩展方法来实现注册。
1. 创建新项目
打开 Visual Studio 2019,点击 Create a new project ,然后选择 ASP.NET Core Web API:
填写项目名称并选择项目路径:
然后选择目标框架,并点击 Create :
2. launchSettings.json 文件
项目创建成功后,在解决方案的 Properties 节点下可以看到 launchSettings.json 文件:
这个文件决定了 ASP.NET Core 应用程序的启动行为,可以看到,它包含了 IIS 和自托管应用(self-hosted)Kestrel 的启动设置的相关配置。
{ "$schema": "http://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:59126", "sslPort": 44389 } }, "profiles": { "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "launchUrl": "weatherforecast", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "CompanyEmployees": { "commandName": "Project", "launchBrowser": true, "launchUrl": "weatherforecast", "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } }
由于我们开发的是 Web API 项目,因此我们并不需要使用浏览器像查看 Web 项目一样来查看 API,我们之后会通过 Postman (以后会介绍)来调用并查看 API 的输出。而为了阻止应用程序启动时自动打开浏览器,需要将 launchBrowser
属性值设置为 false
:
"launchBrowser": false
在创建项目时,如果勾选了 Configure for HTTPS 的复选框,那么在 applicationUrl
节点中就会有两个 URL,一个用于 HTTP,另一个用于 HTTPS。
注意:此 HTTPS 配置项尽在本地环境中有效,当应用程序正式部署后,必需配置真实有效的证书。
在本地开发应用程序时,还有一个很重要的属性:launchUrl
,该属性定义了应用程序启动时默认导航到的 URL。如果要让该属性生效,就需要将 launchBrowser
属性值设置为 true
。例如,如果将 launchUrl
属性值设置为 weatherforecast
,则应用程序启动时会重定向到 https://localhost:5001/weatherforecast。
3. Program.cs 和 Startup.cs
ASP.NET Core 应用程序本质是一个控制台应用程序,它通过创建 web 服务器来托管应用程序并监听传入的HTTP请求,然后返回响应,所以程序的入口还是 Program
类的 Main()
方法,ASP.NET Core Web API 应用程序中的 Program
如下:
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
关于 Host 的启动过程,可以参考:以后补充。
CreateDefaultBuilder(args)
方法设置项目的默认配置文件和变量,以及日志提供程序。在应用启动过程的早期配置好日志提供程序意味着可以使用日志记录发生在启动过程中的问题。
之后,调用 webBuilder.UseStartup<Startup>()
方法来初始化 Startup
类,Startup
类在 ASP.NET Core Web API 项目中是强制要求的类,需要在该类中配置应用程序需要的嵌入式或者自定义的服务,代码如下:
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }
其中,正如方法名字所示,ConfigureServices()
方法用于配置应用程序使用的服务,而服务就是为应用程序添加功能的一些可重用的代码。在 Configure()
方法中将会向应用程序的请求管道添加不同的中间件。
由于较大的应用程序可能包含许多不同的服务,因此在 ConfigureServices()
方法中可能会出现大量的代码,这样会导致代码看起来混乱臃肿、可读性差。为了提高代码可读性,我们可以将添加服务的代码分离成一个个的扩展方法。
4. 扩展方法和 CORS 配置
扩展方法本质上是一种静态方法。它与其他静态方法的不同之处在于,它接受 this
作为第一个参数,this
表示使用该扩展方法的对象的数据类型。
扩展方法必需定义在静态类中,它扩展了.NET 中类型的行为。一旦定义了扩展方法,就可以在同一类型的对象上多次链式调用它。
接下来开始写代码,首先在项目中创建一个新的文件夹:Extensions
然后在该文件夹中创建一个类:ServiceExtensions
,并将这个类改为静态类,代码如下:
public static class ServiceExtensions { }
接下来就开始实现一个具体的功能,这样就能看到应该如何使用静态类。我们要做的第一件事就是在应用程序中配置 CORS。CORS ( Cross-Origin Resource Sharing,跨资源共享 ) 是一种向来自不同域的应用程序授予或者限制访问权限的机制。
如果我们想从不同的域向应用程序发送请求,那就必须配置 CORS。所以接下来就在 ServiceExtensions
类中添加一个扩展方法来允许将来自所有域的所有请求发送到我们的 API:
public static void ConfigureCors(this IServiceCollection services) => services.AddCors(options => { options.AddPolicy("CorsPolicy", builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); });
我们这里暂时使用基本的 CORS 策略设置,因为目前来说允许所有来源 ( origin )、所有类型的方法、所有 header 是可以接受的。但是如果是生产环境,那我们应该尽可能的将策略设置的更严格。
当有需要的时候,我们可以使用 WithOrigins("https://example.com")
方法来限制请求只能来自某个具体源,而不是使用 AllowAnyOrigin()
方法允许来自所有源的请求。同样,可以使用 WithMethods("POST","GET")
方法来限制请求只能是特定的 HTTP 方法,而不是使用 AllowAnyMethods()
方法允许所有类型的 HTTP 方法。另外,可以使用 WithHeaders("accept","content-type")
方法来限制请求包含特定的 headers。
5. IIS 配置
ASP.NET Core 应用默认是自托管(self hosted),当然我们也可以通过配置 IIS 集成来帮助我们将应用使用 IIS 托管,可以通过添加以下扩展方法来实现:
public static void ConfigureIISIntegration(this IServiceCollection services) => services.Configure<IISOptions>(options => { });
目前我们使用默认配置就可以,所以在上述代码中没有初始化 options
的任何属性。如果想修改某些配置,可以参考官方文档:
至此,我们已经编写了用于支持 CORS 和 IIS 集成的扩展方法,接下来就在 Startup
类中进行调用,注意引用命名空间 using CompanyEmployees.Extensions
,ConfigureService()
代码如下:
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { //custom extension methods services.ConfigureCors(); services.ConfigureIISIntegration(); services.AddControllers(); }
对于直接在 ConfigureServices()
方法中添加一系列代码来说,使用扩展方法后可以使代码更简洁,可读性更高。另外扩展方法的命名要尽可能准确、明了。
我们已经成功的将 CORS 和 IIS 配置添加到应用程序的服务容器中,但是还没有真正用到这些服务,所以还需要在 Configure()
方法中添加一些使用服务的代码:
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); //custom pipeline start app.UseStaticFiles(); app.UseCors("CorsPolicy"); app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.All }); //custom pipeline end app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
其中,
UseForwardedHeaders()
:将转发的 header 应用于当前请求上的匹配的字段。按照约定, HTTP 代理以众所周知的 HTTP header 从客户端转发消息。该中间件读取这些 header 并填充 HttpContext
上的相关字段。
UseStaticFiles()
:对当前请求的路径启用静态文件服务,意思就是可以通过路径访问当前目录的文件。如果没有设置静态文件目录的路径,则默认使用 wwwroot 目录。
UseCors()
:将 CORS 中间件添加到应用程序的请求管道中以允许跨域请求。
6. Startup 类中的其它代码
ConfigureServices()
方法中,
AddControllers()
:将控制器的服务添加到服务集合中。AddMvc()
方法也可以将控制器添加到服务集合中,但它除了控制器外,还会将视图和页面添加到服务集合中。我们的项目是 Web API 项目,所以只需要控制器就可以。
Configure()
方法中,
UseRouting()
:将路由中间件添加到请求管道中。
UseAuthorization()
:将授权中间件添加到请求管道中。
UseEndpoints()
:为控制器的 Action 添加终结点并将终结点添加路由中。
中间件的顺序非常重要,以后会单独写一篇关于中间件的文章。
7. 基于环境的设置
在开发应用程序时,我们使用 开发 (development) 环境,当我们发布了应用程序之后就需要使用 生产 (production) 环境。开发环境和生产环境对应不同的 URLs、端口、连接字符串、密码等其它敏感信息。所以我们需要根据环境来区分配置,这在 .NET Core 中是很容易实现的。
当我们创建一个项目后,可以在项目的根目录中看到 appsettings.json
文件,这就我们主要的配置文件,点击文件前面的箭头可以看到一个 appsettings.Development.json
文件。如果在系统的文件资源管理器中打开项目目录,可以看到这是两个不同的文件,但是在 Visual Studio 中,这两个配置文件被关联在了一起。
appsettings.{EnvironmentSuffix}.json
是用于特定环境时的配置文件,可以覆盖 appsettings.json
文件中的配置。如果appsettings.{EnvironmentSuffix}.json
文件中存在与 appsettings.json
文件同名的键值对,则会覆盖键值对的值。另外我们还可以自定义特定的环境,例如,对于生产环境,我们可以添加另一个文件: appsettings.Production.json
:
appsettings.Production.json
文件中应该包含用于生产环境的配置项。
为了设置应用程序运行时的环境,我们需要设置 ASPNETCORE_ENVIRONMENT
环境变量。例如,如果想让应用程序运行在生产环境中,就需要在部署的机器上将上述环境变量的值修改为 Production
。在 Windows 环境中,可以通过输入命令: set ASPNETCORE_ENVIRONMENT=Production
来实现。在 Linux 环境中,可以通过输入命令: export ASPNET_CORE_ENVIRONMENT=Production
来实现。
ASP.NET Core 应用程序通过上述环境变量的值来决定使用哪个 appsettings.json
文件,例如在生产环境中,将会使用 appsettings.Production.json
文件。默认情况下 ASPNETCORE_ENVIRONMENT
变量的值是 Development
,打开 launchSettings.json
文件可以看到:
对于应用程序开发来说,日志记录是非常重要的一项功能,无论是在开发中、还是部署后的使用中,日志都会帮助我们发现、记录问题,我们可以根据日志来定位、复现并修复问题,所以尽可能的早的将日志服务添加到应用程序中是很有必要的,在下一章中我们将会介绍如何配置日志服务。