ASP.NET Core 應(yīng)用使用 Startup 類,按照約定命名為 Startup。 Startup 類:
當(dāng)應(yīng)用啟動(dòng)時(shí),運(yùn)行時(shí)調(diào)用 ConfigureServices 和 Configure:
C#
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)
{
...
}
}
在構(gòu)建應(yīng)用的主機(jī)時(shí),系統(tǒng)為應(yīng)用指定 Startup 類。 在 Program 類的主機(jī)生成器上調(diào)用 Build時(shí),將生成應(yīng)用的主機(jī)。 通常通過在主機(jī)生成器上調(diào)用 WebHostBuilderExtensions.UseStartup<TStartup> 方法來指定 Startup 類:
C#
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
主機(jī)提供 Startup 類構(gòu)造函數(shù)可用的某些服務(wù)。 應(yīng)用通過 ConfigureServices 添加其他服務(wù)。 然后,主機(jī)和應(yīng)用服務(wù)都可以在 Configure 和整個(gè)應(yīng)用中使用。
在 Startup 類中注入依賴關(guān)系的常見用途為注入:
C#
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 的替代方法是使用基于約定的方法。 應(yīng)用為不同的環(huán)境(例如,StartupDevelopment)單獨(dú)定義 Startup 類時(shí),相應(yīng)的 Startup 類會(huì)在運(yùn)行時(shí)被選中。 優(yōu)先考慮名稱后綴與當(dāng)前環(huán)境相匹配的類。 如果應(yīng)用在開發(fā)環(huán)境中運(yùn)行并包含 Startup 類和 StartupDevelopment 類,則使用 StartupDevelopment 類。 有關(guān)詳細(xì)信息,請(qǐng)參閱使用多個(gè)環(huán)境。
要詳細(xì)了解有關(guān)主機(jī)的詳細(xì)信息,請(qǐng)參閱主機(jī)。 有關(guān)在啟動(dòng)過程中處理錯(cuò)誤的信息,請(qǐng)參閱啟動(dòng)異常處理。
典型模式是調(diào)用所有 Add{Service} 方法,然后調(diào)用所有 services.Configure{Service} 方法。 有關(guān)示例,請(qǐng)參閱配置標(biāo)識(shí)服務(wù)。
主機(jī)可能會(huì)在調(diào)用 Startup 方法之前配置某些服務(wù)。 有關(guān)詳細(xì)信息,請(qǐng)參閱主機(jī)。
對(duì)于需要大量設(shè)置的功能,IServiceCollection 上有 Add{Service} 擴(kuò)展方法。 典型 ASP.NET Core 應(yīng)用將為實(shí)體框架、標(biāo)識(shí)和 MVC 注冊(cè)服務(wù):
C#
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
}
將服務(wù)添加到服務(wù)容器,使其在應(yīng)用和 Configure 方法中可用。 服務(wù)通過依賴關(guān)系注入或 ApplicationServices 進(jìn)行解析。
Configure 方法用于指定應(yīng)用響應(yīng) HTTP 請(qǐng)求的方式。 可通過將中間件組件添加到 IApplicationBuilder 實(shí)例來配置請(qǐng)求管道。 Configure 方法可使用 IApplicationBuilder,但未在服務(wù)容器中注冊(cè)。 托管創(chuàng)建 IApplicationBuilder 并將其直接傳遞到 Configure。
ASP.NET Core 模板配置的管道支持:
C#
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();
}
每個(gè) Use 擴(kuò)展方法將一個(gè)或多個(gè)中間件組件添加到請(qǐng)求管道。 例如,UseMvc 擴(kuò)展方法將路由中間件添加到請(qǐng)求管道,并將 MVC 配置為默認(rèn)處理程序。
請(qǐng)求管道中的每個(gè)中間件組件負(fù)責(zé)調(diào)用管道中的下一個(gè)組件,或在適當(dāng)情況下使鏈發(fā)生短路。 如果中間件鏈中未發(fā)生短路,則每個(gè)中間件都有第二次機(jī)會(huì)在將請(qǐng)求發(fā)送到客戶端前處理該請(qǐng)求。
其他服務(wù)(如 IHostingEnvironment 和 ILoggerFactory),也可以在 Configure 方法簽名中指定。如果指定,其他服務(wù)如果可用,將被注入。
有關(guān)如何使用 IApplicationBuilder 和中間件處理順序的詳細(xì)信息,請(qǐng)參閱 ASP.NET Core 中間件。
若要配置服務(wù)和請(qǐng)求處理管道,而不使用 Startup 類,請(qǐng)?jiān)谥鳈C(jī)生成器上調(diào)用 ConfigureServices和 Configure 便捷方法。 多次調(diào)用 ConfigureServices 將追加到另一個(gè)。 如果存在多個(gè) Configure 方法調(diào)用,則使用最后一個(gè) Configure 調(diào)用。
C#
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"];
...
});
}
在應(yīng)用的 Configure 中間件管道的開頭或末尾使用 IStartupFilter 來配置中間件。 IStartupFilter 有助于確保中間件在應(yīng)用請(qǐng)求處理管道的開始或結(jié)束時(shí)由庫添加的中間件之前或之后運(yùn)行。
IStartupFilter 實(shí)現(xiàn)單個(gè)方法(即 Configure),該方法接收并返回 Action<IApplicationBuilder>。IApplicationBuilder 定義用于配置應(yīng)用請(qǐng)求管道的類。 有關(guān)詳細(xì)信息,請(qǐng)參閱使用 IApplicationBuilder 創(chuàng)建中間件管道。
在請(qǐng)求管道中,每個(gè) IStartupFilter 實(shí)現(xiàn)一個(gè)或多個(gè)中間件。 篩選器按照添加到服務(wù)容器的順序調(diào)用。 篩選器可在將控件傳遞給下一個(gè)篩選器之前或之后添加中間件,從而附加到應(yīng)用管道的開頭或末尾。
下面的示例演示如何使用 IStartupFilter 注冊(cè)中間件。
RequestSetOptionsMiddleware 中間件從查詢字符串參數(shù)中設(shè)置選項(xiàng)值:
C#
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"];
if (!string.IsNullOrWhiteSpace(option))
{
_injectedOptions.Value.Option = WebUtility.HtmlEncode(option);
}
await _next(httpContext);
}
}
在 RequestSetOptionsStartupFilter 類中配置 RequestSetOptionsMiddleware:
C#
public class RequestSetOptionsStartupFilter : IStartupFilter
{
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return builder =>
{
builder.UseMiddleware<RequestSetOptionsMiddleware>();
next(builder);
};
}
}
IStartupFilter 在 ConfigureServices 的服務(wù)容器中注冊(cè),參數(shù) Startup 從 Startup 類外部注冊(cè):
C#
WebHost.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddTransient<IStartupFilter,
RequestSetOptionsStartupFilter>();
})
.UseStartup<Startup>()
.Build();
當(dāng)提供 option 的查詢字符串參數(shù)時(shí),中間件在 MVC 中間件呈現(xiàn)響應(yīng)之前處理分配值:
中間件執(zhí)行順序由 IStartupFilter 注冊(cè)順序設(shè)置:
通過 IHostingStartup 實(shí)現(xiàn),可在啟動(dòng)時(shí)從應(yīng)用 Startup 類之外的外部程序集向應(yīng)用添加增強(qiáng)功能。有關(guān)更多信息,請(qǐng)參見在 ASP.NET Core 中使用承載啟動(dòng)程序集。
更多建議: