Startup 類

2019-04-17 08:58 更新

Startup 類

ASP.NET Core 應(yīng)用使用 Startup 類,按照約定命名為 Startup。 Startup 類:

  • 可選擇性地包括 ConfigureServices 方法以配置應(yīng)用的服務(wù)。 服務(wù)是一個提供應(yīng)用功能的可重用組件。 在 ConfigureServices 中配置配置(也稱為“注冊”)并通過依存關(guān)系注入 (DI) 或 ApplicationServices 在整個應(yīng)用中使用。
  • 包括 Configure 方法以創(chuàng)建應(yīng)用的請求處理管道。

當(dāng)應(yīng)用啟動時,運行時調(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)用的主機時,系統(tǒng)為應(yīng)用指定 Startup 類。 在 Program 類的主機生成器上調(diào)用 Build時,將生成應(yīng)用的主機。 通常通過在主機生成器上調(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>();
}

主機提供 Startup 類構(gòu)造函數(shù)可用的某些服務(wù)。 應(yīng)用通過 ConfigureServices 添加其他服務(wù)。 然后,主機和應(yīng)用服務(wù)都可以在 Configure 和整個應(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)單獨定義 Startup 類時,相應(yīng)的 Startup 類會在運行時被選中。 優(yōu)先考慮名稱后綴與當(dāng)前環(huán)境相匹配的類。 如果應(yīng)用在開發(fā)環(huán)境中運行并包含 Startup 類和 StartupDevelopment 類,則使用 StartupDevelopment 類。 有關(guān)詳細(xì)信息,請參閱使用多個環(huán)境。

要詳細(xì)了解有關(guān)主機的詳細(xì)信息,請參閱主機。 有關(guān)在啟動過程中處理錯誤的信息,請參閱啟動異常處理

ConfigureServices 方法

ConfigureServices 方法:

  • 可選。
  • 在 Configure 方法配置應(yīng)用服務(wù)之前,由主機調(diào)用。
  • 其中按常規(guī)設(shè)置配置選項。

典型模式是調(diào)用所有 Add{Service} 方法,然后調(diào)用所有 services.Configure{Service} 方法。 有關(guān)示例,請參閱配置標(biāo)識服務(wù)

主機可能會在調(diào)用 Startup 方法之前配置某些服務(wù)。 有關(guān)詳細(xì)信息,請參閱主機。

對于需要大量設(shè)置的功能,IServiceCollection 上有 Add{Service} 擴展方法。 典型 ASP.NET Core 應(yīng)用將為實體框架、標(biāo)識和 MVC 注冊服務(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 進行解析。

Configure 方法

Configure 方法用于指定應(yīng)用響應(yīng) HTTP 請求的方式。 可通過將中間件組件添加到 IApplicationBuilder 實例來配置請求管道。 Configure 方法可使用 IApplicationBuilder,但未在服務(wù)容器中注冊。 托管創(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();
}

每個 Use 擴展方法將一個或多個中間件組件添加到請求管道。 例如,UseMvc 擴展方法將路由中間件添加到請求管道,并將 MVC 配置為默認(rèn)處理程序。

請求管道中的每個中間件組件負(fù)責(zé)調(diào)用管道中的下一個組件,或在適當(dāng)情況下使鏈發(fā)生短路。 如果中間件鏈中未發(fā)生短路,則每個中間件都有第二次機會在將請求發(fā)送到客戶端前處理該請求。

其他服務(wù)(如 IHostingEnvironment 和 ILoggerFactory),也可以在 Configure 方法簽名中指定。如果指定,其他服務(wù)如果可用,將被注入。

有關(guān)如何使用 IApplicationBuilder 和中間件處理順序的詳細(xì)信息,請參閱 ASP.NET Core 中間件。

便利方法

若要配置服務(wù)和請求處理管道,而不使用 Startup 類,請在主機生成器上調(diào)用 ConfigureServices和 Configure 便捷方法。 多次調(diào)用 ConfigureServices 將追加到另一個。 如果存在多個 Configure 方法調(diào)用,則使用最后一個 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"];

                ...
            });
}

使用 Startup 篩選器擴展 Startup

在應(yīng)用的 Configure 中間件管道的開頭或末尾使用 IStartupFilter 來配置中間件。 IStartupFilter 有助于確保中間件在應(yīng)用請求處理管道的開始或結(jié)束時由庫添加的中間件之前或之后運行。

IStartupFilter 實現(xiàn)單個方法(即 Configure),該方法接收并返回 Action<IApplicationBuilder>。IApplicationBuilder 定義用于配置應(yīng)用請求管道的類。 有關(guān)詳細(xì)信息,請參閱使用 IApplicationBuilder 創(chuàng)建中間件管道。

在請求管道中,每個 IStartupFilter 實現(xiàn)一個或多個中間件。 篩選器按照添加到服務(wù)容器的順序調(diào)用。 篩選器可在將控件傳遞給下一個篩選器之前或之后添加中間件,從而附加到應(yīng)用管道的開頭或末尾。

下面的示例演示如何使用 IStartupFilter 注冊中間件。

RequestSetOptionsMiddleware 中間件從查詢字符串參數(shù)中設(shè)置選項值:

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ù)容器中注冊,參數(shù) Startup 從 Startup 類外部注冊:

C#

WebHost.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddTransient<IStartupFilter, 
            RequestSetOptionsStartupFilter>();
    })
    .UseStartup<Startup>()
    .Build();

當(dāng)提供 option 的查詢字符串參數(shù)時,中間件在 MVC 中間件呈現(xiàn)響應(yīng)之前處理分配值:

瀏覽器窗口顯示已呈現(xiàn)的索引頁。

中間件執(zhí)行順序由 IStartupFilter 注冊順序設(shè)置:

  • 多個 IStartupFilter 實現(xiàn)可能與相同的對象進行交互。 如果順序很重要,請將它們的 IStartupFilter 服務(wù)注冊進行排序,以匹配其中間件應(yīng)有的運行順序。
  • 庫可能添加包含一個或多個 IStartupFilter 實現(xiàn)的中間件,這些實現(xiàn)在向 IStartupFilter注冊的其他應(yīng)用中間件之前或之后運行。 若要在庫的 IStartupFilter 添加中間件之前調(diào)用 IStartupFilter 中間件,請在將庫添加到服務(wù)容器之前定位服務(wù)注冊。 若要在此后調(diào)用,請在添加庫之后定位服務(wù)注冊。

在啟動時從外部程序集添加配置

通過 IHostingStartup 實現(xiàn),可在啟動時從應(yīng)用 Startup 類之外的外部程序集向應(yīng)用添加增強功能。有關(guān)更多信息,請參見在 ASP.NET Core 中使用承載啟動程序集。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號