先說背景,ASP.NET Core 專案在 IIS 執行時有兩種模式 - InProcess 或 OutOfProcess。ASP.NET Core 2.2 以前只支援 OutOfProcess,執行時將啟動一個 Kestrel Process 跑 ASP.NET Core,由 IIS 的 w3wp.exe Process 接收 HTTP Request 再與 Kestrel 溝通。ASP.NET Core 2.2 起增加了 InProcess 模式,ASP.NET Core 直接跑在 IIS AppPool 的 Process 裡,與 OutOfProcess 相比,省去跨 Process 溝通成本,效能可大幅提升。關於 InProcess / OutOfProcess,MVP Rick Strahl 有篇文章針對架構、設定方式與效能做了深入探討,很值得一讀:ASP.NET Core In Process Hosting on IIS with ASP.NET Core

這陣子試玩了一個 ASP.NET Core 3.0 開發的仿 Trello 看板開源專案- Kandu,放在 IIS 執行並打算切成 InProcess 模式。依照 Rick 文章的說明,我改了 .csproj 的 AspNetCoreHostingModel:

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <StartupObject>Kandu.Program</StartupObject>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
  </PropertyGroup>

以及 web.config 的 aspNetCore hostingModel:

<aspNetCore processPath="dotnet" arguments=".\Kandu.dll" forwardWindowsAuthToken="false" stdoutLogEnabled="true" startupTimeLimit="120" requestTimeout="00:05:00" hostingModel="InProcess" stdoutLogFile=".\logs\stdout">

二者原本都是 OutOfProcess,改成 InProcess 後重新 Publish,結果網頁噴出以下錯誤:

System.InvalidOperationException: Application is running inside IIS process but is not configured to use IIS server.
   at Microsoft.AspNetCore.Server.IIS.Core.IISServerSetupFilter.<>c__DisplayClass2_0.<Configure>b__0(IApplicationBuilder app)
   at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
   at Kandu.Program.Main(String[] args) in X:\GitHub\Kandu\App\Program.cs:line 29

經過爬文與挖掘,我理解到這是古老程式翻新才會遇到的罕見問題。Kandu 雖已升級到 .NET 3.0,但 Program.cs 仍使用 1.x 時代的舊寫法 - Host.CreateDefaultBuilder (註:2.0+ 已改用 WebHost.CreateDefaultBuilder(),不需要自己 UseKestrel()、UseIISIntegration(),其中只用了 UseKestrel()。我先補上了 UseIISIntegration() 錯誤依舊,再爬文才知 UseIISIntegration() 是 OutOfProcess 用的,InProcess 要用 UseIIS():

加入 UseIIS() 後問題排除。

查了目前版本 WebHost.ConfigureWebDefaults 的原始碼,已內含 UseKestrel()、UseIIS()、UseIISIntegration(),故 ASP.NET Core 2 之後專案不該有這個問題,會踩到這個雷也算機緣,呵。

A InProcess setup issue of an old ASP.NET Core 3.0 project migrated from 1.x.


Comments

Be the first to post a comment

Post a comment