ASP.NET Core Basic 1-1 WebHost與專案配置

WarrenRyan發表於2019-08-27

.NET Core ASP.NET Core Basic 1-1

本節內容為WebHost與專案配置

專案配置檔案

我們可以很清楚的發現在我們的檔案中含有一個Json檔案——appsettings.json,實際上,這個檔案就是我們專案的預設配置檔案,它內部含有了預設的一些設定,當然你也可以自己進行新增或者修改。這裡我們不展開講述。我們會在本文的後部分進行講解如何讀取、操作配置檔案。

專案主入口Program

在ASP.NET Core2.X的空專案中,你會發現有以下兩個類存在——StarUp、Program,其中Program類裡面就是我們ASP.NET Core的入口(Main函式)。我們可以看一下Program類

namespace ASP.NET_Core_Study
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }
}

我們可以發現,Program中使用了一個 CreateWebHostBuilder 函式進行程式的初始化,裡面就涉及到了我們的WebHost。

那麼什麼是WebHost呢?你可以簡單的理解為就是我們的Web專案的服務主機,它是ASP.NET Core的核心,它呼叫了CreateDefaultBuilder方法進行建立。而泛型函式使用的StartUp則是我們服務的配置類。

當然,WebHost進行服務主機建立的時候你也可以使用 WebHost.Start() 進行手動的配置與建立。這裡我們只針對官方預設的方法進行學習與分析。

首先看到CreateDefaultBuilder()的原始碼,這個你可以在Github或者是ReSharp的反編譯功能檢視到,這裡我是直接從GitHub公開的原始碼複製

 /// <summary>
        /// Initializes a new instance of the <see cref="WebHostBuilder"/> class with pre-configured defaults.
        /// </summary>
        /// <remarks>
        ///   The following defaults are applied to the returned <see cref="WebHostBuilder"/>:
        ///     use Kestrel as the web server and configure it using the application's configuration providers,
        ///     set the <see cref="IHostingEnvironment.ContentRootPath"/> to the result of <see cref="Directory.GetCurrentDirectory()"/>,
        ///     load <see cref="IConfiguration"/> from 'appsettings.json' and 'appsettings.[<see cref="IHostingEnvironment.EnvironmentName"/>].json',
        ///     load <see cref="IConfiguration"/> from User Secrets when <see cref="IHostingEnvironment.EnvironmentName"/> is 'Development' using the entry assembly,
        ///     load <see cref="IConfiguration"/> from environment variables,
        ///     load <see cref="IConfiguration"/> from supplied command line args,
        ///     configure the <see cref="ILoggerFactory"/> to log to the console and debug output,
        ///     and enable IIS integration.
        /// </remarks>
        /// <param name="args">The command line args.</param>
        /// <returns>The initialized <see cref="IWebHostBuilder"/>.</returns>
        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;
        }

你在這裡可以非常清楚的看到,這個函式他會取尋找appsettings.json以及appsettings.{env.EnvironmentName}.json。因此在使用預設的方法進行專案實戰時,我們不應該修改這個檔案的檔名。並且我們可以發現,這個檔案是分兩部分的,一部分是我們的釋出版本(publish),一部分是我們的開發版本。他們的檔名是不同的,在原始碼中我們也可以找到這些語句。同時我們的builder呼叫了UseConfiguration方法,這是一個引數配置的方法,用於接收我們從控制檯輸入的一些引數。

並且,我們可以看到他還進行了服務的替換UseDefaultServiceProvider以及根目錄的設定UseContentRoo,原始碼如下


public static IWebHostBuilder UseContentRoot(this IWebHostBuilder hostBuilder, string contentRoot)
{
    if (contentRoot == null)
    throw new ArgumentNullException(nameof (contentRoot));
    return hostBuilder.UseSetting(WebHostDefaults.ContentRootKey, contentRoot);
}

public IWebHostBuilder UseSetting(string key, string value)
{
    this._config[key] = value;
    return (IWebHostBuilder) this;
}

說到這裡,我需要引出我們ASP.NET Core的兩種啟動方式。一種是使用我們微軟官方的IIS進行專案的部署,他的本質是將dll注入到IIS服務中。當然,我們知道IIS是Windows上的Web伺服器,如果我們要進行跨平臺的開發,我們可以使用微軟開發的Kestrel,原始碼中的ConfigureWebDefaults函式的原始碼我們就可以看到相關的操作

internal static void ConfigureWebDefaults(IWebHostBuilder builder)
        {
            builder.UseKestrel((builderContext, options) =>
            {
                options.Configure(builderContext.Configuration.GetSection("Kestrel"));
            })
            .ConfigureServices((hostingContext, services) =>
            {
                // Fallback
                services.PostConfigure<HostFilteringOptions>(options =>
                {
                    if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)
                    {
                        // "AllowedHosts": "localhost;127.0.0.1;[::1]"
                        var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                        // Fall back to "*" to disable.
                        options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });
                    }
                });
                // Change notification
                services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(
                            new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));

                services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();

                services.AddRouting();
            })
            .UseIIS()
            .UseIISIntegration();
        }

我們可以發現,在這裡,它會從配置檔案中讀取相關的配置進行配置我們啟動使用的服務選項。UseKestrel函式對一些服務進行了註冊,以便後續的使用。這裡我不打算進行詳細的講解,因為這一節內容只是希望你能夠對專案的啟動有一個初步的認識,你需要知道的是,目前位置,我們發現了ASP.NET Core程式會在例項化WebHost之前配置好一切,並且我們可以使用一個開源跨平臺的Web伺服器Kestrel。

StartUp

StartUp類是一個配置性質的類,它裡面有Configure(IApplicationBuilder app, IHostingEnvironment env)以及ConfigureServices(IServiceCollection services)方法,這兩個方法中ConfigureServices是我們的服務配置方法或者說是容器配置,它主要用於配置我們依賴注入的類,而Configure方法是我們配置中介軟體的地方,這兩個概念我會在後一兩篇文章中進行非常詳細的講解。

總結

本篇文章內容並不是很多,主要是讓你知道ASP.NET Core其實只是一個簡答的控制檯程式,只是它呼叫了一些服務而已。

總體來說我們ASP.NET Core的WebHost建立的過程是

  • 配置好伺服器UseKestrel()
  • 配置好根目錄UseContentRoot()
  • 新增配置檔案源ConfigureAppConfiguration((context, builder) => builder.AddJsonFile("appsetting.json", true, true))
  • 註冊日誌記錄到控制檯ConfigureLogging(builder => builder.AddConsole())
  • 配置好StartUp類,進行依賴注入和中介軟體的配置UseStartup()
  • 生成WebHost,Build()返回一個WebHost物件
  • 執行WebHost,Run()將WebHost啟動

當然IWebHostBuilder介面也有一些其他的常見方法,這裡我做一個簡單的列舉

  • UseUrls,配置啟動的Ip地址
  • UseSetting,使用新的檔案替換預設appsettings.json
  • UseShutdownTimeout,自動關機
  • UseEnvironment,配置啟動時的環境(生產Or開發)

這幾個是我經常使用的函式,其他的函式你可以在微軟官方API文件或者是ASP.NET Core的原始碼中進行學習,並不難。

Reference

Asp.netCore 執行

如果我的文章幫助了您,請您在github.NETCoreGuide專案幫我點一個star,在部落格園中點一個關注和推薦。

Github

BiliBili主頁

WarrenRyan'sBlog

部落格園

相關文章