学无止境, 精益求精
十年河东, 十年河西, 莫欺少年穷
学历代表你的过去, 能力代表你的现在, 学习代表你的将来
在探讨 Startup 启动类之前, 我们先来了解下 ASP.NET CORE 配置应用程序的执行顺序, 如下图所示
与早期版本的 ASP.NET 对比, 最显著的变化之一就是配置应用程序的方式, Global.asax,FilterConfig.cs 和 RouteConfig.cs 统统消失了, 取而代之的是 Program.cs 和 Startup.cs.Program.cs 作为 web 应用程序的默认入口, 不做任何修改的情况下, 会调用同目录下 Startup.cs 中的 ConfigureServices 方法 和 Configure 方法.
首先我们来看下 Progarm.cs, 如下
- public class Program
- {
- public static void Main(string[] args)
- {
- CreateWebHostBuilder(args).Build().Run();
- }
- public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
- .UseStartup<Startup>();
- }
- View Code
我们看到 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;
- }
- View Code
- 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();
- }
- View Code
从源码中我们可以看到, CreateDefaultBuilder 执行的任务有:
1, 加载主机和应用程序的配置表信息
2, 配置日志记录
3, 设置 Web 服务器
4, 设置 ASP.NET Core 应用程序的托管形式.
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.
总之, 我们可以初步理解为 Program.cs 主要用来构造, 配置, 并启用项目所依赖的服务器, 最后设置 ASP.NET Core 应用程序的托管形式.
在 Program.cs 中, 我们发现它会引用 Startup.CS, 如下:
- public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
- .UseStartup<Startup>();
下面我们来看看启动类 Startup.CS, 如下:
- public class Startup
- {
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
- public IConfiguration Configuration { get; }
- // This method gets called by the runtime. Use this method to add services to the container.
- public void ConfigureServices(IServiceCollection services)
- {
- services.Configure<CookiePolicyOptions>(options =>
- {
- // This lambda determines whether user consent for non-essential cookies is needed for a given request.
- options.CheckConsentNeeded = context => true;
- options.MinimumSameSitePolicy = SameSiteMode.None;
- });
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
- }
- // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder App, IHostingEnvironment env)
- {
- if (env.IsDevelopment())
- {
- // 如果是开发环境, 允许抛出异常
- App.UseDeveloperExceptionPage();
- }
- else
- {
- // 生产环境, 直接错误页
- App.UseExceptionHandler("/Error");
- App.UseHsts();
- }
- App.UseHttpsRedirection();
- App.UseStaticFiles();
- App.UseCookiePolicy();
- App.UseMvc();
- }
- }
- View Code
Startup 类的作用:
1. ConfigureServices 方法用于定义 (注册) 应用程序所使用的服务.(如: ASP.NET Core MVC,Entity Framework Core,Identity 等);
2. Configure 方法用于定义请求管道的中间件, 该管道将用于处理应用程序的所有请求.
3. 注册服务添加方法是无序的, ASP.NET Core 在应用程序启动的时候, 只要有相应服务即可, 而注册中间件时方法是有序的, 管道内的每一个组件都可以选择是否将请求交给下一个组件, 并在管道中调用下一个组件之前或之后执行某些操作.
1. ConfigureServices
应用通过 ConfigureServices 添加服务. 然后, 主机和应用服务都可以在 Configure 和整个应用中使用.
也就是说在 ConfigureServices 中, 我们...
在 NETCORE 中, 依赖注入几乎无处不在,
未完, 待续... 下班了, 中元节, 不该过多加班的.
来源: http://www.bubuko.com/infodetail-3156894.html