ASP.NET Core Program.cs
在本文中,我们将学习了解 program.cs在asp.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中执行以下操作。
- 将ContentRoot设置为Directory.GetCurrentDirectory。
- 加载可选配置启用记录
- Appsettings.json
- Appsettings.{Environment}.json。
- User secrets。
- 环境变量
- 命令行参数。
- 启用记录
- 设置依赖项注入容器。
- 将Kestre l 配置为Web服务器
- 将框架服务添加到DI容器
- 将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。这基本上将当前目录设置为应用程序的根目录。
加载配置文件:从各种来源按以下顺序加载配置
- Appsettings.json。
- appsettings.{Environment} .json。
- User secrets。
- 环境变量。
- 命令行参数。
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();