ASP.NET Core 中的应用启动App startup in ASP.NET Core

本文内容

作者:Rick AndersonTom DykstraSteve Smith

Startup 类配置服务和应用的请求管道。

Startup 类The Startup class

ASP.NET Core 应用使用 Startup 类,按照约定命名为 StartupStartup 类:

在应用启动时,ASP.NET Core 运行时会调用 ConfigureServicesConfigure

  1. public class Startup
  2. {
  3. public Startup(IConfiguration configuration)
  4. {
  5. Configuration = configuration;
  6. }
  7. public IConfiguration Configuration { get; }
  8. public void ConfigureServices(IServiceCollection services)
  9. {
  10. services.AddRazorPages();
  11. }
  12. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  13. {
  14. if (env.IsDevelopment())
  15. {
  16. app.UseDeveloperExceptionPage();
  17. }
  18. else
  19. {
  20. app.UseExceptionHandler("/Error");
  21. app.UseHsts();
  22. }
  23. app.UseHttpsRedirection();
  24. app.UseStaticFiles();
  25. app.UseRouting();
  26. app.UseAuthorization();
  27. app.UseEndpoints(endpoints =>
  28. {
  29. endpoints.MapRazorPages();
  30. });
  31. }
  32. }

前面的示例适用于 Razor Pages;MVC 版本类似。

在构建应用主机时指定 Startup 类。通常通过在主机生成器上调用 WebHostBuilderExtensions.UseStartup<TStartup> 方法来指定 Startup 类:

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateHostBuilder(args).Build().Run();
  6. }
  7. public static IHostBuilder CreateHostBuilder(string[] args) =>
  8. Host.CreateDefaultBuilder(args)
  9. .ConfigureWebHostDefaults(webBuilder =>
  10. {
  11. webBuilder.UseStartup<Startup>();
  12. });
  13. }

主机提供 Startup 类构造函数可用的某些服务。应用通过 ConfigureServices 添加其他服务。主机和应用服务都可以在 Configure 和整个应用中使用。

使用泛型主机 (IHostBuilder) 时,只能将以下服务类型注入 Startup 构造函数:

  1. public class Startup
  2. {
  3. private readonly IWebHostEnvironment _env;
  4. public Startup(IConfiguration configuration, IWebHostEnvironment env)
  5. {
  6. Configuration = configuration;
  7. _env = env;
  8. }
  9. public IConfiguration Configuration { get; }
  10. public void ConfigureServices(IServiceCollection services)
  11. {
  12. if (_env.IsDevelopment())
  13. {
  14. }
  15. else
  16. {
  17. }
  18. }
  19. }

在调用 Configure 方法之前,大多数服务都不可用。

多启动Multiple Startup

应用为不同的环境(例如,StartupDevelopment)单独定义 Startup 类时,相应的 Startup 类会在运行时被选中。优先考虑名称后缀与当前环境相匹配的类。如果应用在开发环境中运行并包含 Startup 类和 StartupDevelopment 类,则使用 StartupDevelopment 类。有关详细信息,请参阅使用多个环境

请参阅主机,了解有关主机的详细信息。有关在启动过程中处理错误的信息,请参阅启动异常处理

ConfigureServices 方法The ConfigureServices method

ConfigureServices 方法:

  • 可选。
  • Configure 方法配置应用服务之前,由主机调用。
  • 其中按常规设置配置选项

主机可能会在调用 Startup 方法之前配置某些服务。有关详细信息,请参阅主机

对于需要大量设置的功能,IServiceCollection 上有 Add{Service} 扩展方法。例如,AddDbContext、AddDefaultIdentity、AddEntityFrameworkStores 和 AddRazorPages:

  1. public class Startup
  2. {
  3. public Startup(IConfiguration configuration)
  4. {
  5. Configuration = configuration;
  6. }
  7. public IConfiguration Configuration { get; }
  8. public void ConfigureServices(IServiceCollection services)
  9. {
  10. services.AddDbContext<ApplicationDbContext>(options =>
  11. options.UseSqlServer(
  12. Configuration.GetConnectionString("DefaultConnection")));
  13. services.AddDefaultIdentity<IdentityUser>(
  14. options => options.SignIn.RequireConfirmedAccount = true)
  15. .AddEntityFrameworkStores<ApplicationDbContext>();
  16. services.AddRazorPages();
  17. }

将服务添加到服务容器,使其在应用和 Configure 方法中可用。服务通过依赖关系注入ApplicationServices 进行解析。

Configure 方法The Configure method

Configure 方法用于指定应用响应 HTTP 请求的方式。可通过将中间件组件添加到 IApplicationBuilder 实例来配置请求管道。Configure 方法可使用 IApplicationBuilder,但未在服务容器中注册。托管创建 IApplicationBuilder 并将其直接传递到 Configure

ASP.NET Core 模板配置的管道支持:

  1. public class Startup
  2. {
  3. public Startup(IConfiguration configuration)
  4. {
  5. Configuration = configuration;
  6. }
  7. public IConfiguration Configuration { get; }
  8. public void ConfigureServices(IServiceCollection services)
  9. {
  10. services.AddRazorPages();
  11. }
  12. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  13. {
  14. if (env.IsDevelopment())
  15. {
  16. app.UseDeveloperExceptionPage();
  17. }
  18. else
  19. {
  20. app.UseExceptionHandler("/Error");
  21. app.UseHsts();
  22. }
  23. app.UseHttpsRedirection();
  24. app.UseStaticFiles();
  25. app.UseRouting();
  26. app.UseAuthorization();
  27. app.UseEndpoints(endpoints =>
  28. {
  29. endpoints.MapRazorPages();
  30. });
  31. }
  32. }

前面的示例适用于 Razor Pages;MVC 版本类似。

每个 Use 扩展方法将一个或多个中间件组件添加到请求管道。例如,UseStaticFiles 配置中间件提供静态文件

请求管道中的每个中间件组件负责调用管道中的下一个组件,或在适当情况下使链发生短路。

可以在 Configure 方法签名中指定其他服务,如 IWebHostEnvironmentILoggerFactoryConfigureServices 中定义的任何内容。如果这些服务可用,则会被注入。

有关如何使用 IApplicationBuilder 和中间件处理顺序的详细信息,请参阅 ASP.NET Core 中间件

在不启动的情况下配置服务Configure services without Startup

若要配置服务和请求处理管道,而不使用 Startup 类,请在主机生成器上调用 ConfigureServicesConfigure 便捷方法。多次调用 ConfigureServices 将追加到另一个。如果存在多个 Configure 方法调用,则使用最后一个 Configure 调用。

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateHostBuilder(args).Build().Run();
  6. }
  7. public static IHostBuilder CreateHostBuilder(string[] args) =>
  8. Host.CreateDefaultBuilder(args)
  9. .ConfigureAppConfiguration((hostingContext, config) =>
  10. {
  11. })
  12. .ConfigureWebHostDefaults(webBuilder =>
  13. {
  14. webBuilder.ConfigureServices(services =>
  15. {
  16. services.AddControllersWithViews();
  17. })
  18. .Configure(app =>
  19. {
  20. var loggerFactory = app.ApplicationServices
  21. .GetRequiredService<ILoggerFactory>();
  22. var logger = loggerFactory.CreateLogger<Program>();
  23. var env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>();
  24. var config = app.ApplicationServices.GetRequiredService<IConfiguration>();
  25. logger.LogInformation("Logged in Configure");
  26. if (env.IsDevelopment())
  27. {
  28. app.UseDeveloperExceptionPage();
  29. }
  30. else
  31. {
  32. app.UseExceptionHandler("/Home/Error");
  33. app.UseHsts();
  34. }
  35. var configValue = config["MyConfigKey"];
  36. });
  37. });
  38. });
  39. }

使用 Startup 筛选器扩展 StartupExtend Startup with startup filters

使用 IStartupFilter

  • 在应用的 Configure 中间件管道的开头或末尾配置中间件,而无需显式调用 Use{Middleware}IStartupFilter 由 ASP.NET Core 用于将默认值添加到管道的开头,而无需使应用作者显式注册默认中间件。IStartupFilter 允许代表应用作者使用不同的组件调用 Use{Middleware}
  • 创建 Configure 方法的管道。IStartupFilter.Configure 可以将中间件设置为在库添加的中间件之前或之后运行。

IStartupFilter 实现 Configure,即接收并返回 Action<IApplicationBuilder>IApplicationBuilder 定义用于配置应用请求管道的类。有关详细信息,请参阅使用 IApplicationBuilder 创建中间件管道

每个 IStartupFilter 可以在请求管道中添加一个或多个中间件。筛选器按照添加到服务容器的顺序调用。筛选器可在将控件传递给下一个筛选器之前或之后添加中间件,从而附加到应用管道的开头或末尾。

下面的示例演示如何使用 IStartupFilter 注册中间件。RequestSetOptionsMiddleware 中间件从查询字符串参数中设置选项值:

  1. public class RequestSetOptionsMiddleware
  2. {
  3. private readonly RequestDelegate _next;
  4. public RequestSetOptionsMiddleware( RequestDelegate next )
  5. {
  6. _next = next;
  7. }
  8. // Test with https://localhost:5001/Privacy/?option=Hello
  9. public async Task Invoke(HttpContext httpContext)
  10. {
  11. var option = httpContext.Request.Query["option"];
  12. if (!string.IsNullOrWhiteSpace(option))
  13. {
  14. httpContext.Items["option"] = WebUtility.HtmlEncode(option);
  15. }
  16. await _next(httpContext);
  17. }
  18. }

RequestSetOptionsStartupFilter 类中配置 RequestSetOptionsMiddleware

  1. public class RequestSetOptionsStartupFilter : IStartupFilter
  2. {
  3. public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
  4. {
  5. return builder =>
  6. {
  7. builder.UseMiddleware<RequestSetOptionsMiddleware>();
  8. next(builder);
  9. };
  10. }
  11. }

ConfigureServices 中的服务容器中注册 IStartupFilter

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateHostBuilder(args).Build().Run();
  6. }
  7. public static IHostBuilder CreateHostBuilder(string[] args) =>
  8. Host.CreateDefaultBuilder(args)
  9. .ConfigureAppConfiguration((hostingContext, config) =>
  10. {
  11. })
  12. .ConfigureWebHostDefaults(webBuilder =>
  13. {
  14. webBuilder.UseStartup<Startup>();
  15. })
  16. .ConfigureServices(services =>
  17. {
  18. services.AddTransient<IStartupFilter,
  19. RequestSetOptionsStartupFilter>();
  20. });
  21. }

当提供 option 的查询字符串参数时,中间件在 ASP.NET Core 中间件呈现响应之前处理分配值。

中间件执行顺序由 IStartupFilter 注册顺序设置:

  • 多个 IStartupFilter 实现可能与相同的对象进行交互。如果顺序很重要,请将它们的 IStartupFilter 服务注册进行排序,以匹配其中间件应有的运行顺序。

  • 库可能添加包含一个或多个 IStartupFilter 实现的中间件,这些实现在向 IStartupFilter 注册的其他应用中间件之前或之后运行。若要在库的 IStartupFilter 添加的中间件之前调用 IStartupFilter 中间件,请执行以下操作:

    • 在库添加到服务容器之前定位服务注册。
    • 要在此后调用,请在添加库之后定位服务注册。

在启动时从外部程序集添加配置Add configuration at startup from an external assembly

通过 IHostingStartup 实现,可在启动时从应用 Startup 类之外的外部程序集向应用添加增强功能。有关详细信息,请参阅 在 ASP.NET Core 中使用承载启动程序集

其他资源Additional resources

Startup 类The Startup class

ASP.NET Core 应用使用 Startup 类,按照约定命名为 StartupStartup 类:

在应用启动时,ASP.NET Core 运行时会调用 ConfigureServicesConfigure

  1. public class Startup
  2. {
  3. // Use this method to add services to the container.
  4. public void ConfigureServices(IServiceCollection services)
  5. {
  6. ...
  7. }
  8. // Use this method to configure the HTTP request pipeline.
  9. public void Configure(IApplicationBuilder app)
  10. {
  11. ...
  12. }
  13. }

在构建应用主机时指定 Startup 类。通常通过在主机生成器上调用 WebHostBuilderExtensions.UseStartup<TStartup> 方法来指定 Startup 类:

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateWebHostBuilder(args).Build().Run();
  6. }
  7. public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
  8. WebHost.CreateDefaultBuilder(args)
  9. .UseStartup<Startup>();
  10. }

主机提供 Startup 类构造函数可用的某些服务。应用通过 ConfigureServices 添加其他服务。然后,主机和应用服务都可以在 Configure 和整个应用中使用。

Startup 类中注入依赖关系的常见用途为注入:

  1. public class Startup
  2. {
  3. private readonly IHostingEnvironment _env;
  4. private readonly IConfiguration _config;
  5. private readonly ILoggerFactory _loggerFactory;
  6. public Startup(IHostingEnvironment env, IConfiguration config,
  7. ILoggerFactory loggerFactory)
  8. {
  9. _env = env;
  10. _config = config;
  11. _loggerFactory = loggerFactory;
  12. }
  13. public void ConfigureServices(IServiceCollection services)
  14. {
  15. var logger = _loggerFactory.CreateLogger<Startup>();
  16. if (_env.IsDevelopment())
  17. {
  18. // Development service configuration
  19. logger.LogInformation("Development environment");
  20. }
  21. else
  22. {
  23. // Non-development service configuration
  24. logger.LogInformation("Environment: {EnvironmentName}", _env.EnvironmentName);
  25. }
  26. // Configuration is available during startup.
  27. // Examples:
  28. // _config["key"]
  29. // _config["subsection:suboption1"]
  30. }
  31. }

在调用 Configure 方法之前,大多数服务都不可用。

多启动Multiple Startup

应用为不同的环境(例如,StartupDevelopment)单独定义 Startup 类时,相应的 Startup 类会在运行时被选中。优先考虑名称后缀与当前环境相匹配的类。如果应用在开发环境中运行并包含 Startup 类和 StartupDevelopment 类,则使用 StartupDevelopment 类。有关详细信息,请参阅使用多个环境

请参阅主机,了解有关主机的详细信息。有关在启动过程中处理错误的信息,请参阅启动异常处理

ConfigureServices 方法The ConfigureServices method

ConfigureServices 方法:

  • 可选。
  • Configure 方法配置应用服务之前,由主机调用。
  • 其中按常规设置配置选项

主机可能会在调用 Startup 方法之前配置某些服务。有关详细信息,请参阅主机

对于需要大量设置的功能,IServiceCollection 上有 Add{Service} 扩展方法。例如,AddDbContext、AddDefaultIdentity、AddEntityFrameworkStores 和 AddRazorPages:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddDbContext<ApplicationDbContext>(options =>
  4. options.UseSqlServer(
  5. Configuration.GetConnectionString("DefaultConnection")));
  6. services.AddDefaultIdentity<IdentityUser>()
  7. .AddDefaultUI(UIFramework.Bootstrap4)
  8. .AddEntityFrameworkStores<ApplicationDbContext>();
  9. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  10. // Add application services.
  11. services.AddTransient<IEmailSender, AuthMessageSender>();
  12. services.AddTransient<ISmsSender, AuthMessageSender>();
  13. }

将服务添加到服务容器,使其在应用和 Configure 方法中可用。服务通过依赖关系注入ApplicationServices 进行解析。

若要详细了解 SetCompatibilityVersion,请参阅 SetCompatibilityVersion

Configure 方法The Configure method

Configure 方法用于指定应用响应 HTTP 请求的方式。可通过将中间件组件添加到 IApplicationBuilder 实例来配置请求管道。Configure 方法可使用 IApplicationBuilder,但未在服务容器中注册。托管创建 IApplicationBuilder 并将其直接传递到 Configure

ASP.NET Core 模板配置的管道支持:

  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6. }
  7. else
  8. {
  9. app.UseExceptionHandler("/Error");
  10. app.UseHsts();
  11. }
  12. app.UseHttpsRedirection();
  13. app.UseStaticFiles();
  14. app.UseCookiePolicy();
  15. app.UseMvc();
  16. }

每个 Use 扩展方法将一个或多个中间件组件添加到请求管道。例如,UseStaticFiles 配置中间件提供静态文件

请求管道中的每个中间件组件负责调用管道中的下一个组件,或在适当情况下使链发生短路。

可以在 Configure 方法签名中指定其他服务,如 IHostingEnvironmentILoggerFactory,或 ConfigureServices 中定义的任何内容。如果这些服务可用,则会被注入。

有关如何使用 IApplicationBuilder 和中间件处理顺序的详细信息,请参阅 ASP.NET Core 中间件

在不启动的情况下配置服务Configure services without Startup

若要配置服务和请求处理管道,而不使用 Startup 类,请在主机生成器上调用 ConfigureServicesConfigure 便捷方法。多次调用 ConfigureServices 将追加到另一个。如果存在多个 Configure 方法调用,则使用最后一个 Configure 调用。

  1. public class Program
  2. {
  3. public static IHostingEnvironment HostingEnvironment { get; set; }
  4. public static IConfiguration Configuration { get; set; }
  5. public static void Main(string[] args)
  6. {
  7. CreateWebHostBuilder(args).Build().Run();
  8. }
  9. public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
  10. WebHost.CreateDefaultBuilder(args)
  11. .ConfigureAppConfiguration((hostingContext, config) =>
  12. {
  13. })
  14. .ConfigureServices(services =>
  15. {
  16. ...
  17. })
  18. .Configure(app =>
  19. {
  20. var loggerFactory = app.ApplicationServices
  21. .GetRequiredService<ILoggerFactory>();
  22. var logger = loggerFactory.CreateLogger<Program>();
  23. var env = app.ApplicationServices.GetRequiredService<IHostingEnvironment>();
  24. var config = app.ApplicationServices.GetRequiredService<IConfiguration>();
  25. logger.LogInformation("Logged in Configure");
  26. if (env.IsDevelopment())
  27. {
  28. ...
  29. }
  30. else
  31. {
  32. ...
  33. }
  34. var configValue = config["subsection:suboption1"];
  35. ...
  36. });
  37. }

使用 Startup 筛选器扩展 StartupExtend Startup with startup filters

使用 IStartupFilter

  • 在应用的 Configure 中间件管道的开头或末尾配置中间件,而无需显式调用 Use{Middleware}IStartupFilter 由 ASP.NET Core 用于将默认值添加到管道的开头,而无需使应用作者显式注册默认中间件。IStartupFilter 允许代表应用作者使用不同的组件调用 Use{Middleware}
  • 创建 Configure 方法的管道。IStartupFilter.Configure 可以将中间件设置为在库添加的中间件之前或之后运行。

IStartupFilter 实现 Configure,即接收并返回 Action<IApplicationBuilder>IApplicationBuilder 定义用于配置应用请求管道的类。有关详细信息,请参阅使用 IApplicationBuilder 创建中间件管道

每个 IStartupFilter 可以在请求管道中添加一个或多个中间件。筛选器按照添加到服务容器的顺序调用。筛选器可在将控件传递给下一个筛选器之前或之后添加中间件,从而附加到应用管道的开头或末尾。

下面的示例演示如何使用 IStartupFilter 注册中间件。RequestSetOptionsMiddleware 中间件从查询字符串参数中设置选项值:

  1. public class RequestSetOptionsMiddleware
  2. {
  3. private readonly RequestDelegate _next;
  4. private IOptions<AppOptions> _injectedOptions;
  5. public RequestSetOptionsMiddleware(
  6. RequestDelegate next, IOptions<AppOptions> injectedOptions)
  7. {
  8. _next = next;
  9. _injectedOptions = injectedOptions;
  10. }
  11. public async Task Invoke(HttpContext httpContext)
  12. {
  13. Console.WriteLine("RequestSetOptionsMiddleware.Invoke");
  14. var option = httpContext.Request.Query["option"];
  15. if (!string.IsNullOrWhiteSpace(option))
  16. {
  17. _injectedOptions.Value.Option = WebUtility.HtmlEncode(option);
  18. }
  19. await _next(httpContext);
  20. }
  21. }

RequestSetOptionsStartupFilter 类中配置 RequestSetOptionsMiddleware

  1. public class RequestSetOptionsStartupFilter : IStartupFilter
  2. {
  3. public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
  4. {
  5. return builder =>
  6. {
  7. builder.UseMiddleware<RequestSetOptionsMiddleware>();
  8. next(builder);
  9. };
  10. }
  11. }

ConfigureServices 中的服务容器中注册 IStartupFilter

  1. WebHost.CreateDefaultBuilder(args)
  2. .ConfigureServices(services =>
  3. {
  4. services.AddTransient<IStartupFilter,
  5. RequestSetOptionsStartupFilter>();
  6. })
  7. .UseStartup<Startup>()
  8. .Build();

当提供 option 的查询字符串参数时,中间件在 ASP.NET Core 中间件呈现响应之前处理分配值。

中间件执行顺序由 IStartupFilter 注册顺序设置:

  • 多个 IStartupFilter 实现可能与相同的对象进行交互。如果顺序很重要,请将它们的 IStartupFilter 服务注册进行排序,以匹配其中间件应有的运行顺序。

  • 库可能添加包含一个或多个 IStartupFilter 实现的中间件,这些实现在向 IStartupFilter 注册的其他应用中间件之前或之后运行。若要在库的 IStartupFilter 添加的中间件之前调用 IStartupFilter 中间件,请执行以下操作:

    • 在库添加到服务容器之前定位服务注册。
    • 要在此后调用,请在添加库之后定位服务注册。

在启动时从外部程序集添加配置Add configuration at startup from an external assembly

通过 IHostingStartup 实现,可在启动时从应用 Startup 类之外的外部程序集向应用添加增强功能。有关详细信息,请参阅 在 ASP.NET Core 中使用承载启动程序集

其他资源Additional resources