3.1 启动与宿主

3.1.1 应用程序的启动

当ASP.NET Core应用程序启动时,它首先会配置并运行其宿主(Host),宿主主要用来启动、初始化应用程序,并管理其生命周期。

Program类是ASP.NET Core应用程序的入口,它包括一个名为Main的静态方法,当程序运行时,将从这个方法开始执行。这与控制台应用程序(Console Application)完全相同。因此,ASP.NET Core应用程序本质上就是控制台应用程序。以下是Program.cs的内容。

public class Program
{
    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }
}

在Main方法中可以看到,整个程序首先是由CreateWebHostBuilder方法创建一个IWebHostBuilder对象,并调用它的Build方法得到IWebHost对象,然后调用该对象的Run方法运行起来的。在CreateWebHostBuilder方法内部,调用WebHost类的静态方法CreateDefaultBuilder,会返回IWebHostBuilder类型的对象,该对象具有一些默认设定的值,之后又调用了UseStartup方法进一步来配置应用程序的启动。

由CreateDefaultBuilder方法创建IWebHostBuilder对象时所包含的主要默认选项如下。

配置Kestrel服务器作为默认的Web服务器来负责处理Web请求与响应。

使用当前目录作为应用程序的内容目录(ContentRoot),该目录决定了ASP.NET Core查找内容文件(如MVC视图等)的位置。

从以ASPNETCORE_开头的环境变量(如ASPNETCORE_ENVIRONMENT)中以及命令行参数中加载配置项。

从appsettings.josn、appsettings.{Environment}.json、用户机密(仅开发环境)、环境变量和命令行参数等位置加载应用配置。

配置日志功能,默认添加控制台输出与调试输出。

如果应用程序被托管在IIS中,启动IIS集成,它会配置应用程序的主机地址和端口,并允许捕获启动错误等。

因此,CreateDefaultBuilder方法的内容大致如下。

public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
    var builder = new WebHostBuilder();
    if (string.IsNullOrEmpty(builder.GetSetting(WebHostDefaults.ContentRootKey)))
    {
        builder.UseContentRoot(Directory.GetCurrentDirectory());
    }
    if (args != null)
    {
        builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args). Build());
    }
    builder.ConfigureAppConfiguration((hostingContext, config) =>
    {
        var env = hostingContext.HostingEnvironment;
        config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
              .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
        if (env.IsDevelopment())
        {
            var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
            if (appAssembly != null)
            {
                config.AddUserSecrets(appAssembly, optional: true);
            }
        }
        config.AddEnvironmentVariables();
        if (args != null)
        {
            config.AddCommandLine(args);
        }
    })
    .ConfigureLogging((hostingContext, logging) =>
    {
        logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
        logging.AddConsole();
        logging.AddDebug();
        logging.AddEventSourceLogger();
    }).
    UseDefaultServiceProvider((context, options) =>
    {
        options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
    });
    ConfigureWebDefaults(builder);
    return builder;
}

提示

若要查看WebHost的完整代码,需要打开https://github.com/aspnet/AspNetCore,并在它下面查找WebHost.cs文件即可。

CreateDefaultBuilder方法中所包含的默认配置能够通过IWebHostBuilder接口提供的扩展方法进行修改或增加,如ConfigureAppConfiguration、ConfigureKestrel、ConfigureLogging、UseContentRoot和UseUrls等。

ConfigureAppConfiguration方法能够为应用程序添加配置,如果应用程序用到了除appsettings.json和appsettings.{Enviroment}.json之外的其他配置文件,则可以继续调用该方法将配置文件添加进来。

WebHost.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
        config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true);
    })

ConfigureKestrel方法则能够用来配置Kestrel服务器,在下面的例子中,通过KestrelServerOptions对象(即options变量)的属性与方法能够控制Kestrel服务器的行为,如在响应中不包含Server消息头、设置服务器侦听地址与端口、启用HTTPS等。

WebHost.CreateDefaultBuilder(args)
    .ConfigureKestrel((hostingContext, options) =>
    {
        options.AddServerHeader = false;
        options.Listen(IPAddress.Loopback, 6000);
        options.Listen(IPAddress.Loopback, 6001, listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", "testPassword");
        });
})

除了这些以Configure开头的方法外,IWebHostBuilder的其他方法也可以更改WebHost的配置,如UseContentRoot可以修改应用程序的内容目录,使UseEnvironment方法能够修改应用程序的运行环境、UseSetting方法能够修改指定的配置项,UseUrls方法可以修改服务器侦听的IP地址、主机地址以及使用的端口号。

WebHost.CreateDefaultBuilder(args)
    .UseEnvironment(EnvironmentName.Development)
    .UseContentRoot(@"C:\public")
    .UseSetting("https_port","8080")
    .UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")

ASP.NET Core内置了对程序运行环境的支持,通过设置不同的环境,能够使应用程序在运行时获取相应的配置,从而具有不同的行为和逻辑。ASP.NET Core内部提供了如下3个环境名称。

Development:开发。

Staging:预演。

Production:生产。

在程序启动时,它会读取ASPNETCORE_ENVIRONMENT环境变量的值,如果它的值没有设置,那么程序会默认使用Production值。除了读环境变量的值外,还可以使用IWebHostBuilder的UseEnvironment方法来指定,如上例。

由IWebHostBuilder创建的WebHost主要用来作ASP.NET Core应用程序的宿主,除了WebHost外,在ASP.NET Core 2.1中,新增加了通用主机(Generic Host),它主要用于托管非Web应用程序(如运行后台任务的应用),目前它并不支持对Web应用程序的托管,不过,未来在更高的版本中,通用主机将会实现这一功能,并替代WebHost。然而,在目前的版本中,WebHost仍然是托管Web应用所必需的。

当使用IWebHostBuilder的方法配置好宿主后,调用其Build方法,将会生成一个IWebHost实例,它有两个重要的方法,分别是Run和Start,它们都会启动当前宿主;不同的是,前者以阻塞的方式运行宿主,后者则不是。