ASP.NET Core基礎知識(五)【環境(開發、分階段、生產)】

風靈使發表於2019-02-18

ASP.NET Core 基於使用環境變數的執行時環境配置應用行為。

環境

ASP.NET Core 在應用啟動時讀取環境變數 ASPNETCORE_ENVIRONMENT,並將該值儲存在IHostingEnvironment.EnvironmentName中。 ASPNETCORE_ENVIRONMENT 可設定為任意值,但框架支援三個值DevelopmentStagingProduction。 如果未設定 ASPNETCORE_ENVIRONMENT,則預設為 Production

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    if (env.IsProduction() || env.IsStaging() || env.IsEnvironment("Staging_2"))
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseMvc();
}

前面的程式碼:

  • ASPNETCORE_ENVIRONMENT 設定為 Development 時,呼叫 UseDeveloperExceptionPage

  • ASPNETCORE_ENVIRONMENT 的值設定為下列之一時,呼叫 UseExceptionHandler

    • Staging
    • Production
    • Staging_2

環境標記幫助程式使用 IHostingEnvironment.EnvironmentName 的值來包含或排除元素中的標記:

<environment include="Development">
    <div>&lt;environment include="Development"&gt;</div>
</environment>
<environment exclude="Development">
    <div>&lt;environment exclude="Development"&gt;</div>
</environment>
<environment include="Staging,Development,Staging_2">
    <div>
        &lt;environment include="Staging,Development,Staging_2"&gt;
    </div>
</environment>

在 Windows 和 macOS 上,環境變數和值不區分大小寫。 預設情況下,Linux 環境變數和值要區分大小寫。

開發

開發環境可以啟用不應該在生產中公開的功能。 例如,ASP.NET Core 模板在開發環境中啟用了開發人員異常頁

本地計算機開發環境可以在專案的 Properties\launchSettings.json 檔案中設定。 在 launchSettings.json 中設定的環境值替代在系統環境中設定的值。

以下 JSON 顯示 launchSettings.json 檔案中的三個配置檔案:

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:54339/",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_My_Environment": "1",
        "ASPNETCORE_DETAILEDERRORS": "1",
        "ASPNETCORE_ENVIRONMENT": "Staging"
      }
    },
    "EnvironmentsSample": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Staging"
      },
      "applicationUrl": "http://localhost:54340/"
    },
    "Kestrel Staging": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_My_Environment": "1",
        "ASPNETCORE_DETAILEDERRORS": "1",
        "ASPNETCORE_ENVIRONMENT": "Staging"
      },
      "applicationUrl": "http://localhost:51997/"
    }
  }
}

備註
launchSettings.json 中的 applicationUrl 屬性可指定伺服器 URL 的列表。 在列表中的 URL 之間使用分號:

"EnvironmentsSample": {
   "commandName": "Project",
   "launchBrowser": true,
   "applicationUrl": "https://localhost:5001;http://localhost:5000",
   "environmentVariables": {
     "ASPNETCORE_ENVIRONMENT": "Development"
   }
}

使用dotnet run啟動應用時,使用具有 "commandName": "Project" 的第一個配置檔案。 commandName 的值指定要啟動的 Web 伺服器。 commandName 可為以下任一項:

  • IISExpress
  • IIS
  • Project(啟動 Kestrel 的專案)

使用 dotnet run啟動應用時:

  • 如果可用,讀取 launchSettings.jsonlaunchSettings.json 中的 environmentVariables 設定會替代環境變數。
  • 此時顯示承載環境。

以下輸出顯示了使用dotnet run啟動的應用:

PS C:\Websites\EnvironmentsSample> dotnet run
Using launch settings from C:\Websites\EnvironmentsSample\Properties\launchSettings.json...
Hosting environment: Staging
Content root path: C:\Websites\EnvironmentsSample
Now listening on: http://localhost:54340
Application started. Press Ctrl+C to shut down.

Visual Studio 專案屬性“除錯”選項卡提供 GUI 來編輯 launchSettings.json 檔案:

在這裡插入圖片描述
在 Web 伺服器重新啟動之前,對專案配置檔案所做的更改可能不會生效。 必須重新啟動 Kestrel 才能檢測到對其環境所做的更改。

警告
launchSettings.json 不應儲存機密。 機密管理器工具可用於儲存本地開發的機密。

使用 Visual Studio Code時,可以在 .vscode/launch.json 檔案中設定環境變數。 以下示例將環境設定為 Development

{
   "version": "0.2.0",
   "configurations": [
        {
            "name": ".NET Core Launch (web)",

            ... additional VS Code configuration settings ...

            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            }
        }
    ]
}

使用與 Properties/launchSettings.json 相同的方法通過 dotnet run 啟動應用時,不讀取專案中的 .vscode/launch.json 檔案。 在沒有 launchSettings.json 檔案的 Development 環境中啟動應用時,需要使用環境變數設定環境或者將命令列引數設為 dotnet run 命令。

生產

Production 環境應配置為最大限度地提高安全性、效能和應用可靠性。 不同於開發的一些通用設定包括:

  • 快取。
  • 客戶端資源被捆綁和縮小,並可能從 CDN 提供。
  • 已禁用診斷錯誤頁。
  • 已啟用友好錯誤頁。
  • 已啟用生產記錄和監視。 例如,Application Insights

設定環境

為測試設定特定環境通常很有用。 如果未設定環境,預設值為 Production,這會禁用大多數除錯功能。 設定環境的方法取決於作業系統。

Azure 應用服務

若要在 Azure 應用服務中設定環境,請執行以下步驟:

  1. 從“應用服務”邊欄選項卡中選擇應用。
  2. 在“設定”組中,選擇“應用程式設定”邊欄選項卡。
  3. 在“應用程式設定”區域中,選擇“新增新設定”。
  4. 在“輸入名稱”中提供 ASPNETCORE_ENVIRONMENT。 在“輸入值”中提供環境(例如 Staging)。
  5. 交換部署槽位時,如果希望環境設定保持當前槽位,請選中“槽位設定”核取方塊。 有關詳細資訊,請參閱 Azure 文件:交換哪些設定?
  6. 選擇邊欄選項卡頂部的“儲存”。

在 Azure 門戶中新增、更改或刪除應用設定(環境變數)後,Azure 應用服務自動重啟應用。

Windows

若要在使用 dotnet run 啟動該應用時為當前會話設定 ASPNETCORE_ENVIRONMENT,則使用以下命令:

命令提示符

set ASPNETCORE_ENVIRONMENT=Development

PowerShell

$Env:ASPNETCORE_ENVIRONMENT = "Development"

這些命令僅對當前視窗有效。 視窗關閉時,ASPNETCORE_ENVIRONMENT 設定將恢復為預設設定或計算機值。

若要在 Windows 中全域性設定值,請採用下列兩種方法之一:

  • 依次開啟“控制皮膚” > “系統” > “高階系統設定”,再新增或編輯“ASPNETCORE_ENVIRONMENT”值:
    在這裡插入圖片描述
    在這裡插入圖片描述

  • 開啟管理命令提示符並執行 setx 命令,或開啟管理 PowerShell 命令提示符並執行 [Environment]::SetEnvironmentVariable

    命令提示符

    setx ASPNETCORE_ENVIRONMENT Development /M
    

    /M 開關指明,在系統一級設定環境變數。 如果未使用 /M 開關,就會為使用者帳戶設定環境變數。

    PowerShell

    
    [Environment]::SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development", "Machine")
    

    Machine 選項值指明,在系統一級設定環境變數。 如果將選項值更改為 User,就會為使用者帳戶設定環境變數。

如果全域性設定 ASPNETCORE_ENVIRONMENT 環境變數,它就會對在值設定後開啟的任何命令視窗中對 dotnet run 起作用。

web.config

若要使用 web.config 設定 ASPNETCORE_ENVIRONMENT 環境變數,請參閱 ASP.NET Core 模組的“設定環境變數”部分。 使用 web.config 設定 ASPNETCORE_ENVIRONMENT 環境變數後,它的值會替代系統級設定。

專案檔案或釋出配置檔案

對於 Windows IIS 部署:<EnvironmentName> 屬性包含在釋出配置檔案(.pubxml)或專案檔案中。 此方法在釋出專案時設定 web.config 中的環境:

<PropertyGroup>
  <EnvironmentName>Development</EnvironmentName>
</PropertyGroup>

每個 IIS 應用程式池

若要為在獨立應用池中執行的應用設定 ASPNETCORE_ENVIRONMENT 環境變數(IIS 10.0 或更高版本支援此操作),請參閱環境變數 <environmentVariables>主題中的“AppCmd.exe 命令”部分。 為應用池設定 ASPNETCORE_ENVIRONMENT 環境變數後,它的值會替代系統級設定。

重要
在 IIS 中託管應用並新增或更改 ASPNETCORE_ENVIRONMENT 環境變數時,請採用下列方法之一,讓新值可供應用拾取:

  • 在命令提示符處依次執行 net stop was /ynet start w3svc
  • 重啟伺服器。

macOS

設定 macOS 的當前環境可在執行應用時完成:

ASPNETCORE_ENVIRONMENT=Development dotnet run

或者,在執行應用前使用 export 設定環境:

export ASPNETCORE_ENVIRONMENT=Development

.bashrc.bash_profile 檔案中設定計算機級環境變數。 使用任意文字編輯器編輯檔案。 新增以下語句:

export ASPNETCORE_ENVIRONMENT=Development

Linux

對於 Linux 發行版,請在命令提示符中使用 export 命令進行基於會話的變數設定,並使用 bash_profile 檔案進行計算機級環境設定。

按環境配置

若要按環境載入配置,我們建議:

  • appsettings 檔案 (*appsettings.<>.json)。 請參閱配置:檔案配置提供程式
  • 環境變數(在託管應用的每個系統上進行設定)。 請參閱配置:檔案配置提供程式開發環境中應用密碼的安全儲存:環境變數
  • 密碼管理器(僅限開發環境中)。 請參閱 安全儲存中 ASP.NET Core 中開發的應用程式機密

基於環境的 Startup 類和方法

Startup 類約定

ASP.NET Core 應用啟動時,Startup 類啟動應用。 應用可以為不同的環境單獨定義 Startup 類(例如,StartupDevelopment),相應 Startup 類會在執行時得到選擇。 優先考慮名稱字尾與當前環境相匹配的類。 如果找不到匹配的 Startup{EnvironmentName},就會使用 Startup 類。

若要實現基於環境的 Startup 類,請為使用中的每個環境建立 Startup{EnvironmentName} 類,並建立回退 Startup 類:

// Startup class to use in the Development environment
public class StartupDevelopment
{
    public void ConfigureServices(IServiceCollection services)
    {
        ...
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        ...
    }
}

// Startup class to use in the Production environment
public class StartupProduction
{
    public void ConfigureServices(IServiceCollection services)
    {
        ...
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        ...
    }
}

// Fallback Startup class
// Selected if the environment doesn't match a Startup{EnvironmentName} class
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        ...
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        ...
    }
}

使用接受程式集名稱的UseStartup(IWebHostBuilder, String)過載:

public static void Main(string[] args)
{
    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
    var assemblyName = typeof(Startup).GetTypeInfo().Assembly.FullName;

    return WebHost.CreateDefaultBuilder(args)
        .UseStartup(assemblyName);
}

Startup 方法約定

ConfigureConfigureServices支援窗體 Configure<EnvironmentName>Configure<EnvironmentName>Services 的環境特定版本:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        StartupConfigureServices(services);
    }

    public void ConfigureStagingServices(IServiceCollection services)
    {
        StartupConfigureServices(services);
    }

    private void StartupConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        if (env.IsProduction() || env.IsStaging() || env.IsEnvironment("Staging_2"))
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseMvc();
    }

    public void ConfigureStaging(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (!env.IsStaging())
        {
            throw new Exception("Not staging.");
        }

        app.UseExceptionHandler("/Error");
        app.UseHsts();
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseMvc();
    }
}

相關文章