ASP.NET Core Program.cs

在本文中,我们将学习了解 program.csasp.net Core中所扮演的角色。 这是我们配置Web Host的应用程序的入口。 program类配置应用程序基础结构,如Web Host,日志记录,依赖注入容器,IIS集成等。它们是由program类中Main方法的createdefaultbuilder方法创建,配置和构建的。

什么是Program.cs?

Program类包含的Main方法是ASP.NET Core应用的入口点。Main方法类似于控制台应用程序 的Main方法。这是因为所有.NET Core应用程序基本上都是控制台应用程序。我们通过控制台应用程序构建其他类型的应用程序,例如MVC Web应用程序或Razor page 应用程序。

Program类的主要目的是配置应用程序基础结构。

Program类在启动时创建Web Host。然后,它配置日志记录、依赖注入容器、Kestrel Web服务器、IIS集成等。它还将框架服务添加到DI容器中,以便我们可以使用它。 Program类的代码是vs自动生成的,并且对于大多数项目来说很可能已经足够了

什么是web host?

Web host负责启动应用程序并运行它。 在应用程序启动时创建。 Web host创建一个服务器,该服务器侦听HTTP请求。 它配置请求管道(或中间件管道)。 另外,它设置了DI容器,我们在其中添加了服务。 管理服务的生命周期也是Web host的任务。

main方法

打开program.cs。这个类只有一个Main方法 

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace HelloWorld
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

这是我们应用程序的入口。

下图显示了如何创建web host

CreateWebHostBuilder 创建主机并为其提供配置。build方法使用提供的配置进行构建。Run方法运行它,然后侦听HTTP请求

ASP.NET Core中Program.cs类的Main方法

创建主机

CreateWebHostBuilder是static方法,它可以创建和配置主机,然后返回。

 public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });

上面的语法称为“ expression bodied function member(表达式方法体)”。是C#6中引入的功能 。上面的代码与以下代码等效。

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

上面的方法使用Web Host helper静态类。WebHost helper类的CreateDefaultBuilder方法负责使用所需配置创建IWebHostBuilder实例

CreateDefaultBuilder

在CreateDefaultBuilder中执行以下操作。

  1. 将ContentRoot设置为Directory.GetCurrentDirectory。
  2. 加载可选配置启用记录
    1. Appsettings.json
    2. Appsettings.{Environment}.json
    3. User secrets
    4. 环境变量
    5. 命令行参数。
  3. 启用记录
  4. 设置依赖项注入容器。
  5. 将Kestre l 配置为Web服务器
  6. 将框架服务添加到DI容器
  7. 将Kestrel与IIS集成

我们可以从ASP.NET Core元数据包中查看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;
}

让我们来一行一行的看看

设置ContentRoot 

builder.UseContentRoot(Directory.GetCurrentDirectory());

这将ContentRoot设置为 Directory.GetCurrentDirectory。这基本上将当前目录设置为应用程序的根目录。

加载配置文件:从各种来源按以下顺序加载配置

  1. Appsettings.json。
  2. appsettings.{Environment} .json。
  3. User secrets。
  4. 环境变量。
  5. 命令行参数。
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();
}).

这将读取配置文件的“Logging”部分中指定的配置规则,并配置控制台和调试输出的日志记录。

设置DI容器

UseDefaultServiceProvider方法设置并注入依赖项容器。

UseDefaultServiceProvider((context, options) =>
{
  options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
});

配置WebHost

最后,代码调用ConfigureWebDefaults方法。此方法配置Web Host

internal static void ConfigureWebDefaults(IWebHostBuilder builder)
{
    builder.ConfigureAppConfiguration((ctx, cb) =>
    {
        if (ctx.HostingEnvironment.IsDevelopment())
        {          StaticWebAssetsLoader.UseStaticWebAssets(ctx.HostingEnvironment, ctx.Configuration);
        }
    });
    builder.UseKestrel((builderContext, options) =>
    {     options.Configure(builderContext.Configuration.GetSection("Kestrel"));
    })
    .ConfigureServices((hostingContext, services) =>
    {
        services.PostConfigure<HostFilteringOptions>(options =>
        {
            if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)
            {
               var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
               options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });

            }
        });
                    new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));
        services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();
        if (string.Equals("true", hostingContext.Configuration["ForwardedHeaders_Enabled"], StringComparison.OrdinalIgnoreCase))
        {
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
                        options.KnownNetworks.Clear();
                options.KnownProxies.Clear();
            });
            services.AddTransient<IStartupFilter, ForwardedHeadersStartupFilter>();
        }
        services.AddRouting();
    })
    .UseIIS()
    .UseIISIntegration();
}

Kestrel

第一种方法告诉主机使用Kestrel Web服务器。Kestrel是基于跨平台托管HTTP服务器的。该服务器允许ASP.NET Core应用程序在Windows以外的操作系统上运行

builder.UseKestrel((builderContext, options) =>
{
options.Configure(builderContext.Configuration.GetSection("Kestrel"));
})

配置服务

配置服务并将其添加到DI 容器。

ConfigureServices((hostingContext, services) =>
{
   //服务
}

使用IIS或集成

配置IIS服务器以托管应用程序。我们可以通过两种方式托管应用程序。一个在进程中托管,另一个在进程外托管。in Process在IIS Process内部运行该应用程序,并由配置UseIIS()。Out of process在单独的进程中运行,并使用Kestrel服务器。然后,IIS充当反向代理,将请求转发到Kestrel。这是通过方法配置的UseIISIntegration()。

.UseIIS()
.UseIISIntegration();

Startup class

主机已创建和配置,但是在构建和运行之前,我们需要使用应用程序进行进一步配置。我们在Startup类中执行此操作。默认情况下,该类被命名为Startup类。通过使用UseStartup方法,我们使构建者知道启动类的位置

.UseStartup<Startup>()

启动类包含两个方法。一个是ConfigureServices(是可选的),另一个是Configure。在ConfigureServices方法中,我们配置在应用程序中创建的服务并将其添加到DI容器中。在Configure方法中,我们通过添加中间件的方式来创建请求管道。

CreateWebHostBuilder将从启动类调用ConfigureServices和configure方法,并进一步配置主机

编译并运行

CreateWebHostBuilder创建Web Host并将其返回。通过Build与Run方法调用,并且启动应用程序从而开始监听HTTP请求。

CreateWebHostBuilder(args).Build().Run();
posted @ 2020-10-25 19:41  N-COUNT  阅读(2260)  评论(0编辑  收藏  举报