(15)ASP.NET Core2.2 Web主機(IWebHostBuilder)

1.前言

ASP.NET Core應用程序能夠配置和啓動主機(Host)。主機負責應用程序啓動和生命週期管理,配置服務器和請求處理管道。主機還能夠設置日誌記錄、依賴關係注入和配置。而Host主機又包括Web主機(IWebHostBuilder)和通用主機(IHostBuilder)。該章節主要介紹了用於託管Web應用的Web主機。對於其餘類型的應用,請使用通用主機。web

2.設置主機

建立使用IWebHostBuilder實例的主機。一般在應用程序的入口點來執行Main方法。在項目模板中,Main位於Program.cs。典型應用默認調用CreateDefaultBuilder來開始建立主機:json

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

2.1執行下列任務

調用CreateDefaultBuilder的代碼位於名爲CreateWebHostBuilder的方法中,這讓它區分於 Main中對生成器對象調用Run的代碼。CreateDefaultBuilder執行下列任務:
●使用應用程序的託管配置提供應用程序將Kestrel服務器配置爲Web服務器。
●將內容根設置爲由 Directory.GetCurrentDirectory返回的路徑。
●經過如下對象加載主機配置:
  ○前綴爲ASPNETCORE_的環境變量(例如,ASPNETCORE_ENVIRONMENT)。
  ○命令行參數。
●按如下順序加載應用程序配置:
  ○appsettings.json。
  ○appsettings.{Environment}.json。
  ○應用在使用入口程序集的Development環境中運行時的機密管理器。
  ○環境變量。
  ○命令行參數。
●配置控制檯和調試輸出的日誌記錄。日誌記錄包含appsettings.json或appsettings.{Environment}.json文件的日誌記錄配置部分中指定的日誌篩選規則。
●使用ASP.NET Core模塊在IIS後面運行時,CreateDefaultBuilder會啓用IIS集成,這會配置應用程序的基址和端口。IIS集成還配置應用程序以捕獲啓動錯誤。
●若是應用環境爲「開發(Development)」,請將ServiceProviderOptions.ValidateScopes設爲true。服務器

2.2重寫和加強定義的配置

ConfigureAppConfiguration、ConfigureLogging以及IWebHostBuilder的其餘方法和擴展方法可重寫和加強CreateDefaultBuilder定義的配置。下面是一些示例:
ConfigureAppConfiguration:用於指定應用程序的其餘IConfiguration。下面的ConfigureAppConfiguration調用添加委託,以在appsettings.xml文件中添加應用程序配置,該示例在Core系列第11章節有演示。可屢次調用ConfigureAppConfiguration。請注意,此配置不適用於主機(例如,服務器URL或環境)。app

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
        config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true);
});

ConfigureLogging:ConfigureLogging調用添加委託,將最小日誌記錄級別 (SetMinimumLevel)配置爲LogLevel.Warning。此設置重寫CreateDefaultBuilder在appsettings.Development.json和appsettings.Production.json中配置,分別爲LogLevel.Debug和LogLevel.Error。可屢次調用 ConfigureLogging。框架

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
    .ConfigureLogging(logging =>
    {
        logging.SetMinimumLevel(LogLevel.Warning);
});

ConfigureKestrel:調用ConfigureKestrel來重寫CreateDefaultBuilder在配置Kestrel時創建的30,000,000字節默認Limits.MaxRequestBodySize:async

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
    .ConfigureKestrel((context, options) =>
    {
        options.Limits.MaxRequestBodySize = 20000000;
});

設置主機時,能夠提供配置和ConfigureServices方法。若是指定Startup類,必須定義Configure方法。ide

3.主機配置值

WebHostBuilder依賴於如下的方法設置主機配置值:
●主機生成器配置,其中包括格式ASPNETCORE_{configurationKey}的環境變量。例如 ASPNETCORE_ENVIRONMENT。
●UseContentRoot和UseConfiguration等擴展。
●UseSetting和關聯鍵。使用UseSetting設置值時,該值設置爲不管何種類型的字符串。函數

3.1應用程序鍵(名稱)

在主機構造期間調用UseStartup或Configure時,會自動設置 IHostingEnvironment.ApplicationName屬性。該值設置爲包含應用入口點的程序集的名稱。要顯式設置值,請使用WebHostDefaults.ApplicationKey(環境變量:ASPNETCORE_APPLICATIONNAME):post

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //應用程序默認名稱爲:CoreWeb (也就是項目名稱)
  string an = env.ApplicationName;
  ...
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args).UseStartup<Startup>() .UseSetting(WebHostDefaults.ApplicationKey, "CoreWeb");

3.2捕獲啓動錯誤

此設置控制啓動錯誤的捕獲。當false時,啓動期間出錯致使主機退出。當true時,主機在啓動期間捕獲異常並嘗試啓動服務器(環境變量:ASPNETCORE_CAPTURESTARTUPERRORS)。學習

WebHost.CreateDefaultBuilder(args)
    .CaptureStartupErrors(true)

3.3內容根

此設置肯定ASP.NET Core開始搜索內容文件,如MVC視圖等。內容根也用做Web根設置的基路徑。若是路徑不存在,主機將沒法啓動(環境變量:ASPNETCORE_CONTENTROOT)。

WebHost.CreateDefaultBuilder(args)
    .UseContentRoot("c:\\<content-root>")

3.4詳細錯誤

肯定是否應捕獲詳細錯誤。啓用(或當環境設置爲Development)時,應用捕獲詳細的異常(環境變量:ASPNETCORE_DETAILEDERRORS)。

WebHost.CreateDefaultBuilder(args)
    .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")

3.5環境

設置應用程序的環境。環境能夠設置爲任何值。框架定義的值包括Development、Staging和Production。值不區分大小寫。默認狀況下,從ASPNETCORE_ENVIRONMENT環境變量讀取環境。使用Visual Studio時,可能會在launchSettings.json文件中設置環境變量。有關於環境詳情信息,能夠移步到Core系列第10章節有參閱(環境變量:ASPNETCORE_ENVIRONMENT)。

WebHost.CreateDefaultBuilder(args)
    .UseEnvironment(EnvironmentName.Development)

3.6HTTPS端口

設置HTTPS重定向端口。用於強制實施HTTPS(環境變量:ASPNETCORE_HTTPS_PORT)。

WebHost.CreateDefaultBuilder(args)
    .UseSetting("https_port", "8080")

3.7服務器(Kestrel) URL

指示IP地址或主機地址,其中包含服務器應針對請求偵聽的端口和協議。設置爲服務器應響應的以分號分隔 (;) 的URL前綴列表。例如 http://localhost:123。使用「*」指示服務器應針對請求偵聽的使用特定端口和協議(例如 http://*:5000)的IP地址或主機名。協議(http://或https://)必須包含每一個URL。不一樣的服務器支持的格式有所不一樣(環境變量:ASPNETCORE_URLS)。

WebHost.CreateDefaultBuilder(args)
    .UseUrls("https://*:5000;https://localhost:5001;https://hostname:5002")

4.重寫配置

使用配置能夠配置Web主機。在下面的示例中,主機配置是根據須要在hostsettings.json文件中指定。命令行參數可能會重寫從hostsettings.json文件加載的任何配置。生成的配置(在config中)用於經過UseConfiguration配置主機。
新建一個hostsettings.json文件,內容以下:

{
  "urls": "https://*:5005"
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
    //IConfigurationBuilder的配置主機
    var config = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        //主機配置在hostsettings.json文件中指定
        .AddJsonFile("hostsettings.json", optional: true)
        //輸入的命令行參數可能會重寫從hostsettings.json文件加載的任何配置
        .AddCommandLine(args)
        .Build();

    return WebHost.CreateDefaultBuilder(args)
        .UseUrls("https://*:5001")
        .UseConfiguration(config)
        .Configure(app =>
        {
            //生成的配置委託函數
            app.Run(context =>
                context.Response.WriteAsync("Hello, World!"));
        });
}

上述代碼描述意思是若要指定在特定的URL上運行的主機,所需的值能夠在執行dotnet運行時從命令提示符傳入。命令行參數重寫hostsettings.json文件中的urls值,且服務器偵聽端口8080:

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

主機啓動時,先用hostsettings.json config重寫UseUrls提供的urls參數配置,而後再用命令行參數config重寫hostsettings.json config的urls參數配置。

5.管理主機

管理主機啓動方式有Run和Start兩種。Run方法啓動Web應用程序並阻止調用線程,直到關閉主機。Start方法經過調用自身以非阻止方式運行主機。

//Run
CreateWebHostBuilder(args).Build().Run();
//Start:非阻止方式,全部必須加上ReadLine
CreateWebHostBuilder(args).Build().Start();
Console.ReadLine();

6.IHostingEnvironment接口

IHostingEnvironment接口提供有關應用的Web承載環境的信息。使用構造函數注入獲取 IHostingEnvironment以使用其屬性和擴展方法:

//示例1:
public class CustomFileReader
{
    private readonly IHostingEnvironment _env;

    public CustomFileReader(IHostingEnvironment env)
    {
        _env = env;
    }
    public string ReadFile(string filePath)
    {
        var fileProvider = _env.WebRootFileProvider;
        // Process the file here
    }
}

能夠用於在啓動時基於環境配置應用程序或者將IHostingEnvironment注入到Startup構造函數,用於ConfigureServices:

//示例2:
public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        HostingEnvironment = env;
    }
    public IHostingEnvironment HostingEnvironment { get; }
    public void ConfigureServices(IServiceCollection services)
    {
        if (HostingEnvironment.IsDevelopment())
        {
            // Development configuration
        }
        else
        {
            // Staging/Production configuration
        }
        var contentRootPath = HostingEnvironment.ContentRootPath;
    }
}

IHostingEnvironment服務還能夠直接注入到Configure方法以設置處理管道:

//示例3:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        // In Development, use the Developer Exception Page
        app.UseDeveloperExceptionPage();
    }
    else
    {
        // In Staging/Production, route exceptions to /error
        app.UseExceptionHandler("/error");
    }
    var contentRootPath = env.ContentRootPath;
}

建立自定義中間件(要了解中間件的同窗們,能夠移步到第四章節學習)時能夠將IHostingEnvironment 注入Invoke方法:

public async Task Invoke(HttpContext context, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        // Configure middleware for Development
    }
    else
    {
        // Configure middleware for Staging/Production
    }
    var contentRootPath = env.ContentRootPath;
}

7.IApplicationLifetime接口

IApplicationLifetime容許後啓動和關閉活動。接口上的三個屬性是用於註冊Action方法(用於定義啓動和關閉事件)的取消標記。

取消標記

觸發條件

ApplicationStarted

主機已徹底啓動。

ApplicationStopped

主機正在完成正常關閉。應處理全部請求。 關閉受到阻止,直到完成此事件。

ApplicationStopping

主機正在執行正常關閉。仍在處理請求。關閉受到阻止,直到完成此事件。

public class Startup
{
    public void Configure(IApplicationBuilder app, IApplicationLifetime appLifetime)
    {
        appLifetime.ApplicationStarted.Register(OnStarted);
        appLifetime.ApplicationStopping.Register(OnStopping);
        appLifetime.ApplicationStopped.Register(OnStopped);
        Console.CancelKeyPress += (sender, eventArgs) =>
        {
            appLifetime.StopApplication();
            // Don't terminate the process immediately, wait for the Main thread to exit gracefully.
            eventArgs.Cancel = true;
        };
    }
    private void OnStarted()
    {
        // Perform post-startup activities here
    }
    private void OnStopping()
    {
        // Perform on-stopping activities here
    }
    private void OnStopped()
    {
        // Perform post-stopped activities here
    }
}

StopApplication是請求應用終止的意思。如下類在調用類的Shutdown方法時使用StopApplication正常關閉應用:

public class MyClass
{
    private readonly IApplicationLifetime _appLifetime;
    public MyClass(IApplicationLifetime appLifetime)
    {
        _appLifetime = appLifetime;
    }
    public void Shutdown()
    {
        _appLifetime.StopApplication();
    }
}

8.做用域驗證

若是應用環境爲「開發(Development)」,則CreateDefaultBuilder將ServiceProviderOptions.ValidateScopes設爲true。若將ValidateScopes設爲true,默認服務提供應用程序會執行檢查來驗證如下內容:
●做用域服務不能直接或間接地從根服務提供者解析。
●做用域服務不會直接或間接地注入到單例中(服務的生命週期)。
若要始終驗證做用域(包括在生命週期環境中驗證),請使用主機生成器上的 UseDefaultServiceProvider配置ServiceProviderOptions:

WebHost.CreateDefaultBuilder(args)
    .UseDefaultServiceProvider((context, options) => {
        options.ValidateScopes = true;
})


參考文獻:
ASP.NET Core Web主機

相關文章
相關標籤/搜索