閱讀465 返回首頁    go 阿裏雲 go 技術社區[雲棲]


[WCF REST] WebServiceHost有何特別之處?

WCF為REST服務的寄宿提供了一個新的ServiceHost,即WebServiceHost。WebServiceHost是ServiceHost的子類,而WebServiceHostFactory是對應的ServiceHostFactory,在基於IIS/WAS寄宿中被使用。由於對REST服務絕大部分功能的支持都是通過WebHttpBehavior這麼一個終結點行為實現的,所以WebServiceHost的核心功能就是將該終結點行為應用到寄宿服務的所有終結點。除此之外,WebServiceHost還具有一些額外的功能,這些功能都是通過重寫OnOpening方法實現的。

由於WebHttpBehavior提供了幫助頁麵,所以當我們通過WebServiceHost對REST服務進行寄宿的時候會屏蔽掉通過ServiceDebugBehavior服務行為提供的幫助頁麵。由於通過服務行為ServiceMetadataBehavior實現的元數據發布機製是基於SOAP的,如果我們在寄宿服務上應用了ServiceMetadataBehavior行為,WebServiceHost也會將基於HTTP-GET的元數據發布功能屏蔽。我們可以通過一個簡單的實例來證實這一點。

   1: using (WebServiceHost host = new WebServiceHost(typeof(EmployeesService)))
   2: {
   3:     ServiceDebugBehavior serviceDebug = 
   4:     host.Description.Behaviors.Find<ServiceDebugBehavior>();
   5:     if (null == serviceDebug)
   6:     {
   7:         serviceDebug = new ServiceDebugBehavior();
   8:         host.Description.Behaviors.Add(serviceDebug);
   9:     }
  10:     serviceDebug.HttpHelpPageEnabled = true;
  11:     serviceDebug.HttpsHelpPageEnabled = true;
  12:  
  13:     ServiceMetadataBehavior serviceMetadata = 
  14:     host.Description.Behaviors.Find<ServiceMetadataBehavior>();
  15:     if (null == serviceMetadata)
  16:     {
  17:         serviceMetadata = new ServiceMetadataBehavior();
  18:         host.Description.Behaviors.Add(serviceMetadata);
  19:     }
  20:     serviceMetadata.HttpGetEnabled = true;
  21:     serviceMetadata.HttpsGetEnabled = true;
  22:     host.Open();
  23:  
  24:     Console.WriteLine("ServiceDebugBehavior");
  25:     Console.WriteLine("\t{0, -20}: {1}", "HttpHelpPageEnabled", serviceDebug.HttpHelpPageEnabled);
  26:     Console.WriteLine("\t{0, -20}: {1}\n", "HttpsHelpPageEnabled", serviceDebug.HttpsHelpPageEnabled);
  27:  
  28:     Console.WriteLine("ServiceMetadataBehavior");
  29:     Console.WriteLine("\t{0, -20}: {1}", "HttpGetEnabled", serviceMetadata.HttpGetEnabled);
  30:     Console.WriteLine("\t{0, -20}: {1}", "HttpsGetEnabled", serviceMetadata.HttpsGetEnabled);
  31: }

在如上所示的代碼片斷中,我們分別將服務行為ServiceDebugBehavior和ServiceMetadataBehavior應用在寄宿服務上,並將其HttpHelpPageEnabled/HttpsHelpPageEnabled和HttpGetEnabled/HttpsGetEnabled屬性設置為True。在開啟WebServiceHost之後我們將兩個服務行為的這4個屬性打印出來。從如下所示的輸出結果我們可以看出這四個屬性最終被設置成了False。

   1: ServiceDebugBehavior
   2:     HttpHelpPageEnabled : False
   3:     HttpsHelpPageEnabled: False
   4:  
   5: ServiceMetadataBehavior
   6:     HttpGetEnabled      : False
   7:     HttpsGetEnabled     : False

終結點是由地址、綁定和契約三要素構成,所謂標準終結點,就是基於典型的通信場景選擇組成終結點的要素(主要是綁定和契約)進而創建出一個標準的終結點。如果我們在使用WebServiceHost進行服務寄宿的時候指定一個基地址,在沒有添加任何終結點的情況下WebServiceHost會在開啟過程中自動添加一個類型(Kind)為webHttpEndpoint 的標準終結點。我們同樣可以通過實例演示來證實這一點。

   1: Uri baseAddress = new Uri("http://127.0.0.1:3721/employees");
   2: using (WebServiceHost host = 
   3:     new WebServiceHost(typeof(EmployeesService), baseAddress))
   4: {
   5:     host.Open();
   6:     ServiceEndpoint endpoinit = host.Description.Endpoints[0];
   7:     Console.WriteLine("{0,-8}: {1}", "Address", endpoinit.Address);
   8:     Console.WriteLine("{0,-8}: {1}", "Binding", endpoinit.Binding);
   9:     Console.WriteLine("{0,-8}: {1}", "Contract", endpoinit.Contract.ContractType);
  10: }

在沒有提供任何配置的情況下,我們通過如上的代碼借助於WebServiceHost進行服務寄宿。在基於服務類型創建的WebServiceHost中指定了一個基地址,並在開啟WebServiceHost之後,我們獲取第一個終結點並將其三要素打印出來。從如下所示的輸出結果我們可以看出:WebServiceHost基於服務類型實現的契約接口IEmployees創建了一個終結點,該終結點采用指定的基地址作為其地址,綁定類型為WebHttpBinding。

   1: Address : http://127.0.0.1:3721/employees
   2: Binding : System.ServiceModel.WebHttpBinding
   3: Contract: Artech.WcfServices.Service.Interface.IEmployees

正如上麵所說,WebServiceHost除了完成從ServiceHost繼承下來的服務寄宿功能之外,其隻要的職責就是將WebHttpBehavior行為應用到寄宿服務的所有終結點上。也就是說,當我們開啟WebServiceHost的時候,如果終結點沒有應用WebHttpBehavior行為,會自動創建一個新的WebHttpBehavior對象應用到終結點上。WebHttpBehavior的自動添加可以通過如下代碼中的調試斷言來體現。

   1: using (WebServiceHost host = new WebServiceHost(typeof(EmployeesService)))
   2: {
   3:     foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
   4:     {
   5:         WebHttpBehavior behavior = endpoint.Behaviors.Find<WebHttpBehavior>();
   6:         if (null != behavior)
   7:         {
   8:             endpoint.Behaviors.Remove(behavior);
   9:         }
  10:     }        
  11:     host.Open();
  12:     foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
  13:     {
  14:         Debug.Assert(null != endpoint.Behaviors.Find<WebHttpBehavior>());
  15:     }      
  16: }

作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-26 14:04:10

  上一篇:go  [WCF REST] 幫助頁麵與自動消息格式(JSON/XML)選擇
  下一篇:go  構建理想的模塊自測結構