Asp.Net Core 入門(一)——Program.cs做了什么


  ASP.NET Core 是微軟推出的一種全新的跨平台開源 .NET 框架,用於在 Windows、Mac 或 Linux 上生成基於雲的新式 Web 應用程序。國內目前關於Asp.Net Core的書比較少,自己靠着閱讀微軟官方文檔,源碼和在52ABP梁老師的教程中慢慢的在一點點的積累Asp.Net Core的知識。因此希望將自己的學習記錄下來,以此鞏固和交流。

  閑話不多說,我們知道學習一門新的技術,最好的方法就是從它的啟動入口進行跟蹤,那么接下來我們先來看下Asp.Net Core的入口文件Program.cs。

  筆者使用的.Net SDK 是 2.2版本,所以下面的介紹都是基於2.2版本的。

    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中Main函數很像我們之前的Console應用程序,那么它當中的CreateWebHostBuilder究竟做了什么事情呢?既然.Net Core是開源的,我們看源碼就方便了很多,接下來就從源碼來了解下它究竟做了什么工作。

     /// <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;
        }
 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();
        }

  從源碼中我們可以看到,CreateDefaultBuilder執行的任務有:

  1、加載主機和應用程序的配置表信息

  2、配置日志記錄

  3、設置Web服務器

  4、設置Asp.Net Core應用程序的托管形式。

  現在我們來看一下Asp.Net Core是如何加載配置的。

  訪問配置信息可以通過 IConfiguration 接口進行訪問,我們從源碼也可以看到,Asp.Net Core加載配置的過程,它們之間是按照順序如果有相同的配置會依次被覆蓋:appsettings.json,appsettings{Environment}.json(應用程序配置文件) -->User Secrets(用戶機密) --> Environment Variables(環境變量) --> Command-line arguments(命令行參數)。

  其中應用程序配置文件的{Environment}可以在項目的屬性中調試進行配置,如果項目中不存在單獨為某個環境配置的,采用appsettings.json。

  應用程序配置文件我們比較清楚,以前在.Net Framework我們有web.config,但是Asp.Net Core中出現了User Secrets用戶機密,那么它有什么用呢,其實它可以保存我們比較敏感的配置信息,比如第三方的Key,像微信的Appkey之類的。那我們該如何添加User Secrets呢?我們需要在命令行的窗口下,切換到我們項目的執行文件夾下,即bin所在的那層目錄,運行命令dotnet user-secrets set [KeyName] [KeyValue]

  接着我們就可以在VS項目中查看到該用戶機密了

  

  Environment variables(環境變量)在 Properties文件夾下的launchSettings.json進行配置

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:4084",
      "sslPort": 44338
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "StudentManagement": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

  這里的profiles可以在VS調試運行的時候做選擇

  而Command-line arguments(命令行參數)需要結合命令行窗口執行: dotnet run KeyName="KeyValue"。

  那么我們怎么獲取配置信息呢? Asp.Net Core提供了ConfigureAppConfiguration 可以給我們調用獲取配置,在StartUp文件中可以使用 _configuration["KeyName"] 來獲取。

   最后,我們再看一下Asp.Net Core應用程序的托管形式,它有兩種托管形式:進程內托管InProcess和進程外托管OutOfProcess。我們知道Asp.Net Core是可以自托管的,它默認托管形式就是InProcess。那么這兩種方式的區別是什么呢?

  InProcess:配置進程內托管在項目.csproj文件中 <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>,在InProcess托管情況下,CreateDefaultBuilder()方法調用UseIIS()方法並在IIS工作進程(w3wp.exe或iisexpress.exe)內托管應用程序,從性能角度,InProcess托管比OutOfProcess托管提供了更高的請求吞吐量。

  OutOfProcess:有2個Web服務器-內部Web服務器和外部Web服務器,內部Web服務器是Kestrel,托管進程是dotnet.exe;外部web服務器可以是iis,nginx,apache。

 

  現在我們知道了CreateDefaultBuilder做了什么工作了,那么在它之后調用了UseStartup<Startup>(),那Startup做了什么工作呢,我們下篇再來討論。

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM