天天看點

WCF技術剖析之六:為什麼在基于ASP.NET應用寄宿(Hosting)下配置的BaseAddress無效

本篇文章來源于幾天前一個朋友向我咨詢的問題。問題是這樣的,他說他采用ASP.NET應用程式的方式對定義的WCF服務進行寄宿(Hosting),并使用配置的方式對服務的BaseAddress進行了設定,但是在建立ServiceHost的時候卻抛出InvalidOperationException,并提示相應Address Scheme的BaseAddress找不到。我意識到這可能和WCF中用于判斷服務寄宿方式的邏輯有關,于是我讓這位朋友将相同的服務寄宿代碼和配置遷移到GUI程式或者Console應用中,看看是否正常。結果如我所想,一切正常,個人覺得這應該是WCF的一個Bug。今天撰文與大家讨論,看看大家對這個問題有何見解。

一、問題重制

問題很容易重制,假設我們通過ASP.NET應用對服務CalculatorService進行寄宿,為了簡單起見,我将服務契約和服務實作定義在一起。CalculatorService的定義如下面的代碼片斷所示:

我們把服務寄宿的代碼定義在一個Web Page的Load事件中。但程式執行到到建立ServiceHost的時候,抛出如下圖所示的InvalidOperationException異常。

<a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/WCFASP.NETHostingBaseAddress_1092C/image_2.png" target="_blank"></a>

WCF技術剖析之六:為什麼在基于ASP.NET應用寄宿(Hosting)下配置的BaseAddress無效

下面是錯誤資訊和異常的StackTrace:

二、問題分析

通過上面提供StackTrace,我們可以看到錯誤發生在WCF試圖将BaseAddress和RelativeAddress進行組合生成AbsoluteAddress的時候。從錯誤消息可以看出,在進行位址的組合時,由于沒有找到适合綁定類型(WsHttpBinding)Scheme(http)的BaseAddress,導緻了異常的抛出。

要解答這個問題,首先要解釋一下WCF的BaseAddress在不同服務寄宿(Service Hosting)方式下的定義方式。對于WCF服務的自我寄宿(Self Hosting)或者采用Windows Service進行服務寄宿,我們可以通過代碼或者形如上面的配置為服務指定一系列的BaseAddress(對于一個既定的URI Scheme,隻能由唯一的BaseAddress)。但是對于采用IIS或者WAS進行服務寄宿,我們需要為相應的服務定義一個.svc檔案,我們通過通路.svc檔案的方式來調用相應的服務。對于後者,.svc檔案得位址就是WCF服務的BaseAddress,是以WCF會忽略BaseAddress的配置。

那麼WCF采用怎樣的方式來判斷目前服務寄宿的方式是基于IIS呢,還是其他呢?答案是通過System.Web.Hosting.HostingEnvironment的靜态屬性IsHosted。對于ASP.NET有一定了解的人應該很清楚,在一個ASP.NET應用下,該屬性永遠傳回為True。也就是說,WCF會把基于ASP.NET應用的服務寄宿,看成是基于IIS的服務寄宿,這顯然是不對的。

WCF對BaseAddress配置的加載和添加的邏輯定義在ServiceHostBase的LoadHostConfig方法中,大緻的邏輯如下面的代碼所示:

三、解決方式

其實這種情況也沒有什麼好的解決方案,不外乎就是避免通過配置的方式設定服務的BaseAddress,可以通過代碼的方式來設定。如下面的代碼所示:

另一種方式就是采用絕對位址的方式定義終結點:

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。