在 ASP.NET 應用(非 IIS .svc 模式)中以配置檔設定 <baseAddresses>,建立 ServiceHost 卻拋出 InvalidOperationException:「找不到符合 scheme http 的基底位址」。同樣代碼移至 Console/WPF 應用卻正常運作。本文深入原始碼揭示根因並給出解決方案。
<service name="CalculatorService">
<host>
<baseAddresses>
<add baseAddress="https://127.0.0.1:3721/services" />
</baseAddresses>
</host>
<endpoint address="calculatorservice" binding="wsHttpBinding" contract="CalculatorService" />
</service>
ASP.NET Page_Load 中 new ServiceHost(typeof(CalculatorService)) 即拋出異常。StackTrace 指向 ServiceHostBase.MakeAbsoluteUri 找不到 BaseAddress。
WCF 判斷寄宿環境的關鍵邏輯在 ServiceHostBase.LoadHostConfig:
if (!ServiceHostingEnvironment.IsHosted) // 僅非託管環境才載入 baseAddresses 配置
{
// 載入 <baseAddresses> 並加入 baseAddresses 集合
}
ServiceHostingEnvironment.IsHosted 內部委派 HostingEnvironmentWrapper.IsHosted → System.Web.Hosting.HostingEnvironment.IsHosted。在任何 ASP.NET 應用(含 WebForm、MVC)中,此屬性永遠回傳 true。WCF 因此將 ASP.NET 自寄宿誤判為 IIS/WAS 寄宿,直接忽略配置檔中的 <baseAddresses>。
protected void Page_Load(object sender, EventArgs e)
{
_host = new ServiceHost(typeof(CalculatorService),
new Uri("https://127.0.0.1:3721/services"));
_host.Open();
}
<endpoint address="https://127.0.0.1:3721/services/calculatorservice"
binding="wsHttpBinding" contract="CalculatorService" />
這本質上是 WCF 設計時將「ASP.NET 應用」等同於「IIS 寄宿」的決策導致。在 ASP.NET 自寄宿場景,請勿依賴配置檔 BaseAddress,改用建構函式傳入 Uri 或端點絕對位址。