ASP.NET Core托管

原文:Hosting
作者:Steve Smith
翻译:娄宇(Lyrics)
校对:何镇汐许登洋(Seay)

为了运行 ASP.NET Core 应用程序,你需要使用 WebHostBuilder 配置和启动一个宿主.

什么是宿主?

ASP.NET Core 应用程序需要在宿主中执行。宿主必须实现 IWebHost 接口,这个接口暴露了功能和服务的集合,以及 Start 方法。宿主通常使用 WebHostBuilder 的实例进行创建,该实例构建并返回一个 WebHost 实例。WebHost 引用服务器来处理请求。学习更多关于 服务器

宿主和服务器的不同之处是什么?

宿主负责应用程序启动和生命周期管理。服务器负责接受 HTTP 请求。确保应用程序服务和服务器可用并正确配置也是宿主职责的一部分。你可以把宿主看作是服务器的包装。宿主被配置为使用一个特定的服务器;服务器并不知道它的宿主。

设置宿主

使用 WebHostBuilder 实例创建一个宿主。这通常是在你的应用程序入口点:public static void Main,(在项目模板的 Program.cs 文件中)。一个典型的 Program.cs 如下所示,演示如何使用 WebHostBuilder 来构建一个宿主。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;

namespace WebApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>()
                .Build();

            host.Run();
        }
    }
}

WebHostBuilder 负责创建宿主,宿主会启动应用程序服务器。WebHostBuilder 需要你提供实现了 IServer (上面代码中的 UseKestrel) 接口的服务器。 UseKestrel 指定应用程序会使用 Kestrel 服务器。

服务器的 内容根 ( content root ) 决定它将在哪里搜索内容文件,比如 MVC 视图文件。默认的内容根是应用程序运行的文件夹。

注解
指定 Directory.GetCurrentDirectory 作为内容根时,当应用程序启动时会使用 Web 项目的根目录作为应用程序的内容根(比如,从 Web 项目文件夹调用 dotnet run)。Visual Studio 和 dotnet new 的模板是默认使用 Directory.GetCurrentDirectory 作为内容根的。

如果应用程序需要使用 IIS,需要在构建宿主时调用 UseIISIntegration 方法。注意这不是像 UseKestrel 那样配置一个 服务器。为了让 ASP.NET Core 使用 IIS,你必须同时指定 UseKestrelUseIISIntegration。Kestrel 被设计为在代理后运行而不应该直接部署到互联网。UseIISIntegration 指定 IIS 为反向代理服务器。

注解
UseKestrelUseIISIntegration 行为区别非常大。IIS 只是作为一个反向代理。UseKestrel 创建 Web 服务器并且对代码进行托管。UseIISIntegration 指定 IIS 作为反向代理服务器。它同时也检查了 IIS/IISExpress 使用的环境变量并做出比如使用哪个动态端口,设置什么 Header 等决定。然而它不处理或者创建 IServer

配置一个宿主(以及一个 ASP.NET Core 应用程序)的最小实现仅仅包含一个服务器和应用程序请求管道的配置:

var host = new WebHostBuilder()
    .UseKestrel()
    .Configure(app =>
    {
        app.Run(async (context) => await context.Response.WriteAsync("Hi!"));
    })
    .Build();

host.Run();

注解
当设置一个宿主,你可以提供 ConfigureConfigureServices 方法,或者定义一个 Startup 类(也必须定义这些方法,参见 :doc:startup)。多次调用 ConfigureServices 会进行追加配置;多次调用 Configure 或者 UseStartup 会替换之前的设置。

配置宿主

WebHostBuilder 提供了方法用于为宿主设置大多数可用的配置值,它也可以被设置为直接使用 UseSetting 以及相关的键。比如,指定应用程序名字:

new WebHostBuilder()
    .UseSetting("applicationName", "MyApp")

宿主配置值

应用程序名 string
键: applicationName。这个配置设定指定的值将从 IHostingEnvironment.ApplicationName 返回。

捕获启动异常 bool
键: captureStartupErrors。默认是 false。当值为 false 时,在启动过程中的错误会导致宿主退出。当值为 true 时,宿主会捕捉 Startup 类中的任何异常,并试图启动服务器。同时将为每个请求显示错误页面(一般的,或详细的,这取决于下面提到的详细错误设置)。 可使用 CaptureStartupErrors 方法设置。

new WebHostBuilder()
    .CaptureStartupErrors(true)

内容根 string
Key: contentRoot。默认是应用程序集所在的文件夹(针对 Kestrel;IIS 默认使用 Web 项目根目录)。这个设置决定了 ASP.NET Core 从哪里开始搜索内容文件,比如 MVC 视图。内容根同时被作为 Web 根设置 的基础路径使用。可使用 UseContentRoot 方法设置。路径必须是存在的,否则宿主会启动失败。

new WebHostBuilder()
    .UseContentRoot("c:\\mywebsite")

详细错误 bool
键: detailedErrors。默认是 false。当值是 true 时(或者当环境设置为“Development”时),应用程序会显示详细的启动错误信息,而不仅仅是一般的错误页。可使用 UseSetting 设置。

new WebHostBuilder()
    .UseSetting("detailedErrors", "true")

当详细错误设置为 false 并且捕捉启动异常是 true 时,服务器在每个请求的(错误)响应中显示一般错误页。

当详细错误设置为 true 并且捕捉启动异常是 true 时,服务器在每个请求的(错误)响应中显示详细错误页。

环境 string
键: environment。默认是“Production”。可以设置为任何值。框架定义的值包含“Development”,“Staging”,以及“Production”。值不区分大小写。参见 environments。可使用 UseEnvironment 方法设置。

new WebHostBuilder()
    .UseEnvironment("Development")

注解
默认情况下,环境是从 ASPNETCORE_ENVIRONMENT 环境变量中读取。当使用 Visual Studio,环境变量可能在 launchSettings.json 文件中进行设置。

服务器 URLs string
键: urls。设置分号(;)来分隔服务器应该响应的 URL 前缀。比如,"http://localhost:123"。域名可以用“*”替换,表明服务器需要针对任何使用指定端口及协议的 IP 地址或域名监听请求(比如,“http://*:5000”或者https://*:5001”)。协议(“http://”或者“https://”)必须包含在每个URL里。前缀由配置好的服务器解释;服务器之间支持的格式会有所不同。

new WebHostBuilder()
    .UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")

启动程序集 string
键: startupAssembly。决定搜索 Startup 类的程序集。可使用 UseStartup 方法设置。可以使用 WebHostBuilder.UseStartup<StartupType> 指定特定的引用类型。如果调用多次 UseStartup 方法,最后一个调用的生效。

new WebHostBuilder()
    .UseStartup("StartupAssemblyName")

Web 根 string
键: webroot。如果不指定,默认是 (Content Root Path)\wwwroot,如果该路径存在。如果这个路径不存在,则使用一个没有文件操作的提供器。可使用 UseWebRoot 方法设置。

new WebHostBuilder()
    .UseWebRoot("public")

使用 configuration 来设置宿主所需的配置值。这些值可能随后被重写。可使用 UseConfiguration 指定。

public static void Main(string[] args)
{
  var config = new ConfigurationBuilder()
    .AddCommandLine(args)
    .AddJsonFile("hosting.json", optional: true)
    .Build();

  var host = new WebHostBuilder()
    .UseConfiguration(config)
    .UseKestrel()
    .Configure(app =>
    {
      app.Run(async (context) => await context.Response.WriteAsync("Hi!"));
    })
  .Build();

  host.Run();
}

在上面的例子中,可以通过命令行参数配置宿主,或者在 hosting.json 文件中进行配置。要指定在特定的网址上运行宿主,你可以从命令行传递所需要的值:

dotnet run --urls "http://*:5000"

Run 方法启动 Web 应用程序并且阻止调用线程,直到宿主关闭。

host.Run();

你可以通过调用宿主的 Start 方法来以非阻塞方式运行宿主。

using (host)
{
  host.Start();
  Console.ReadLine();
}

传递一个 URL 列表到 Start 方法,它将监听指定的 URL:

var urls = new List<string>() {
  "http://*:5000",
  "http://localhost:5001"
  };
var host = new WebHostBuilder()
  .UseKestrel()
  .UseStartup<Startup>()
  .Start(urls.ToArray());

using (host)
{
  Console.ReadLine();
}

排序的重要性

WebHostBuilder 首先读取某些环境变量中的设置(如果环境变量中设置了)。这些环境变量必须采用格式 ASPNETCORE_{configurationKey},因此假如要设置默认情况下服务器监听的 URL,你需要设置 ASPNETCORE_URLS

你可以通过指定配置来重写任何环境变量(使用 UseConfiguration)或者明确地设置值(例如使用 UseUrls)。宿主会使用任何选项最后设置的值。因此,UseIISIntegration 必须出现在 UseUrls 之后,因为它将替换 IIS 动态提供的 URL。如果你想以编程方式设置默认 URL 的值,但是允许他通过配置重写,你需要如下配置宿主:

var config = new ConfigurationBuilder()
.AddCommandLine(args)
.Build();

var host = new WebHostBuilder()
    .UseUrls("http://*:1000") // default URL
    .UseConfiguration(config) // override from command line
    .UseKestrel()
    .Build();