这篇文章简单记录 ASP.NET Core 中 ,startup 类的一些使用.
一. 前言
在 Startup 类中, 一般有两个方法:
ConfigureServices 方法: 用来配置应用的 service .
Configure 方法: 创建应用的请求处理管道
它们都在应用启动时, 被 ASP.NET Core runtime 调用:
- public class Startup
- {
- // Use this method to add services to the container.
- public void ConfigureServices(IServiceCollection services)
- {
- ...
- }
- // Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder App)
- {
- ...
- }
- }
当应用的 host 被 built(建立)时, Startup 类被指定到应用中.
而在 Program 中, 当 host builder 上的 Build 被调用时, 应用的 host 被 built .
而 Startup 类是通过调用 webHostBuilderExtensions.UseStartup<TStartup > 方法指定的.
- public class Program
- {
- public static void Main(string[] args)
- {
- CreateWebHostBuilder(args).Build().Run(); //Build 方法被调用时, 应用的 host 被建立, 同时 Startup 被指定到应用中
- }
- public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
- .UseStartup<Startup>();
- }
在 startup 类中, 一种依赖注入的常见用法:
IHostingEnvironment : 根据 enviironment (环境) 配置 services .
IConfiguration : 读取配置
ILoggerFactory : 在 Startup.ConfigureServices 中创建 logger .
- public class Startup
- {
- private readonly IHostingEnvironment _env;
- private readonly IConfiguration _config;
- private readonly ILoggerFactory _loggerFactory;
- public Startup(IHostingEnvironment env, IConfiguration config,
- ILoggerFactory loggerFactory)
- {
- _env = env;
- _config = config;
- _loggerFactory = loggerFactory;
- }
- public void ConfigureServices(IServiceCollection services)
- {
- var logger = _loggerFactory.CreateLogger<Startup>();
- if (_env.IsDevelopment())
- {
- // Development service configuration
- logger.LogInformation("Development environment");
- }
- else
- {
- // Non-development service configuration
- logger.LogInformation($"Environment: {_env.EnvironmentName}");
- }
- // Configuration is available during startup.
- // Examples:
- // _config["key"]
- // _config["subsection:suboption1"]
- }
- }
注入 IHostingEnvironment , 当定义不同环境的 Startup (例如, StartupDevelopment 等), 在运行时, 选择合适的 Startup.
二. ConfigureServices 方法
它有三个特点:
可选的
在调用 Configure 方法之前调用 ConfigureServices
Configuration options 按约定设置
1. 比较典型的是调用 Add{Service} 和 services.Configure{Service} . 例如: Configure Identity services.
2. host 可能会 在 Startup 方法被调用之前, 配置一些服务. 例如: The host.
在 startup 被调用之前, CreateDefaultBuilder 方法配置了一个 host .
3. Add{Service}是 IServiceCollection 的扩展方法, 下面是一些使用:
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddDbContext<ApplicationDbContext>(options =>
- options.UseSqlServer(
- Configuration.GetConnectionString("DefaultConnection")));
- services.AddDefaultIdentity<IdentityUser>()
- .AddDefaultUI(UIFramework.Bootstrap4)
- .AddEntityFrameworkStores<ApplicationDbContext>();
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
- // Add application services. 添加应用的服务
- services.AddTransient<IEmailSender, AuthMessageSender>();
- services.AddTransient<ISmsSender, AuthMessageSender>();
- }
添加 services 到 service container 使它们在应用和 Configure 方法中可用. services 方法可以通过 dependency injection 或 ApplicationServices 解析.
三. The Configure method
Configure 方法用来指定应用怎样 处理 HTTP request. 请求管道 (request pipeline) 通过添加中间组件到 IApplicationBuilder 实例中来配置.
ASP.NET Core 模板 配置的管道:
- Developer Exception Page
- Exception handler
- HTTP Strict Transport Security (HSTS)
- HTTPS redirection
- Static files
- General Data Protection Regulation (GDPR)
- ASP.NET Core MVC and Razor Pages
- 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();
- }
使用 Use 扩展方法添加一个或多个中间组件到请求管道. 例如, UseMvc 扩展方法添加 Routing Middleware 到请求管道 并且配置 MVC 作为一个默认的处理器.
四. Convenience methods
不使用 Startup 类配置 services 和 request processing pipeline. 在 host builder 上调用 ConfigureServices 和 Configure 的简便方法. 如果存在多个 ConfigureServices 的调用, 会依次添加. 如果存在多个 Configure 方法的调用, 最后一个 Configure 的调用会被使用.
- public class Program
- {
- public static IHostingEnvironment HostingEnvironment { get; set; }
- public static IConfiguration Configuration { get; set; }
- public static void Main(string[] args)
- {
- CreateWebHostBuilder(args).Build().Run();
- }
- public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
- .ConfigureAppConfiguration((hostingContext, config) =>
- {
- })
- .ConfigureServices(services =>
- {
- ...
- })
- .Configure(App =>
- {
- var loggerFactory = App.ApplicationServices
- .GetRequiredService<ILoggerFactory>();
- var logger = loggerFactory.CreateLogger<Program>();
- var env = App.ApplicationServices.GetRequiredServices<IHostingEnvironment>();
- var config = App.ApplicationServices.GetRequiredServices<IConfiguration>();
- logger.LogInformation("Logged in Configure");
- if (env.IsDevelopment())
- {
- ...
- }
- else
- {
- ...
- }
- var configValue = config["subsection:suboption1"];
- ...
- });
- }
五. Extend Startup with startup filters (使用 startup filter 扩展 Startup)
使用 IStartupFilter , 在应用的 Configure 中间件管道的开头或末尾配置中间件.
IStartupFilter 实现 Configure 方法, 它会接收和返回一个 Action<IApplicationBuilder>. 而 IApplicationBuilder 定义了一个类来配置一个应用的请求管道.
这些 filters 会按照添加到 services container 的顺序被调用.
下面是一个例子:
- RequestSetOptionsMiddleware
- public class RequestSetOptionsMiddleware
- {
- private readonly RequestDelegate _next;
- private IOptions<AppOptions> _injectedOptions;
- public RequestSetOptionsMiddleware(
- RequestDelegate next, IOptions<AppOptions> injectedOptions)
- {
- _next = next;
- _injectedOptions = injectedOptions;
- }
- public async Task Invoke(HttpContext httpContext)
- {
- Console.WriteLine("RequestSetOptionsMiddleware.Invoke");
- var option = httpContext.Request.Query["option"]; // 取请求中的 option 参数
- if (!string.IsNullOrWhiteSpace(option))
- {
- _injectedOptions.Value.Option = WebUtility.htmlEncode(option);
- }
- await _next(httpContext);
- }
- }
RequestSetOptionsMiddleware 中间件被配置在 RequestSetOptionsStartupFilter 类中:
- public class RequestSetOptionsStartupFilter : IStartupFilter
- {
- public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
- {
- return builder =>
- {
- builder.UseMiddleware<RequestSetOptionsMiddleware>();
- next(builder);
- };
- }
- }
IStartupFilter 在 ConfigureServices 中被注册到 service container, 并且从 Startup 类的外部增强 Startup:
- WebHost.CreateDefaultBuilder(args)
- .ConfigureServices(services =>
- {
- services.AddTransient<IStartupFilter,
- RequestSetOptionsStartupFilter>();
- })
- .UseStartup<Startup>()
- .Build();
当 option 的查询字符串存在时, 中间件会在 MVC 中间件之前处理这个值
中间件的执行顺序是按照 IStartupFilter 的注册顺序
六. 补充
这里晚上补充下 ApplicationServices 解析 services 的使用
参考网址:
来源: https://www.cnblogs.com/Vincent-yuan/p/11105523.html