微軟 WCF的幾種寄宿方式,寄宿IIS、寄宿winform、寄宿控制臺、寄宿Windows服務
WCF寄宿方式是一種非常靈活的操作,可以在IIS服務、Windows服務、Winform程序、控制臺程序中進行寄宿,從而實現WCF服務的運行,為調用者方便、高效提供服務調用。本文分別對這幾種方式進行詳細介紹並開發例子進行說明,以求大家對WCF寄宿的方式進行全面的認識和了解。
1、 WCF服務的IIS服務寄宿
我在我前面幾篇WCF開發框架的介紹文章中,介紹過了WCF常用的一種寄宿方式,IIS服務寄宿。這種寄宿方式是最為方便的方式,而且由於服務只需要IIS運行就能自動運行起來,因此廣為使用。
創建這種方式IIS寄宿方式的,只需要在解決方案裏面,添加WCF服務應用程序,就可以生成這種的服務模塊了。
這個是一個基於Web的應用程序,創建項目後會生成一個Service1.svc的服務頁面,以及相關的WCF服務接口和實現,如下圖所示。
這個就是簡單的WCF服務,當然如果是復雜的實際應用,會考慮和數據庫打交道,而且可能項目會分成幾個進行管理,從而實現更好的邏輯分離操作。
2、 創建WCF服務庫為多種寄宿做準備
除了上面常用的IIS服務寄宿,一般還會有各種各樣的寄宿方式,不過如果采用其他方式的寄宿方式,一般會把WCF服務和寄宿方式進行項目的分離,實現更好的重用操作,特別WCF需要考慮多種寄宿方式的情況下。下面是WCF服務庫和WCF服務應用程序的介紹說明,先了解一下基礎。
WCF服務庫,可以認為是一個包含WCF服務以及契約定義的類庫。這裏WCF服務庫還不能直接運行,你可以在其他項目裏引用,在宿主裏啟用托管這個庫。
而WCF應用程序,是一個可以執行的程序,它有獨立的進程,WCF服務類契約的定義,可以直接看到運行的效果。此項目模板應該是基於IIS托管的程序。
前者一般考慮WCF服務設計的時候,服務類的定義為單獨的庫,可以為其它項目使用。提高代碼的復用性。後者在開發基於IIS托管的WCF服務程序時,比較多見,自學的時候也可以使用這種類型。當然你也可以修改這些代碼,比如把WCF服務程序裏的類,移到一個單獨的類庫裏。
創建WCF服務庫,可以理解為我們開發.NET程序時創建的一個類庫模塊,不含界面,如下所示,創建一個WCF服務庫。
確定後就只有一個示例服務Service1生成了。
這裏,我們為了演示,就不修改任何它們的代碼,原始的代碼如下所示。
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace WcfServiceLibrary { public class Service1 : IService1 { public string GetData(int value) { return string.Format("You entered: {0}", value); } public CompositeType GetDataUsingDataContract(CompositeType composite) { if (composite == null) { throw new ArgumentNullException("composite"); } if (composite.BoolValue) { composite.StringValue += "Suffix"; } return composite; } } }
3、 WCF服務的控制臺程序寄宿
這種也是一種常見的WCF服務寄宿方式,通過啟動一個類似DOS窗口的控制臺軟件,實現WCF服務的動態寄宿,關閉控制臺程序,服務就自然終止。
這種方式很簡單,創建一個控制臺程序,然後添加WCF服務類庫的項目應用,在Main函數裏面添加下面代碼即可實現。
namespace WcfService_HostConsole { class Program { static void Main(string[] args) { try { ServiceHost serviceHost = new ServiceHost(typeof(Service1)); if (serviceHost.State != CommunicationState.Opened) { serviceHost.Open(); } Console.WriteLine("WCF 服務正在運行......"); Console.WriteLine("輸入回車鍵 <ENTER> 退出WCF服務"); Console.ReadLine(); serviceHost.Close(); } catch (Exception ex) { Console.WriteLine(ex); } } } }
4、 WCF服務的Winform程序寄宿
和控制臺程序一樣,我們創建一個Winform項目,然後在窗體啟動代碼裏面添加寄宿方式的代碼即可,為了較好的響應體驗,可以使用後臺線程程序進行服務啟動,如下所示。
namespace WcfService_HostWinform { public partial class FrmMain : Form { ServiceHost serviceHost = null; BackgroundWorker worker = null; public FrmMain() { InitializeComponent(); worker = new BackgroundWorker(); worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); worker.DoWork += new DoWorkEventHandler(worker_DoWork); if (!worker.IsBusy) { tssTips.Text = "正在啟動......"; lblTips.Text = tssTips.Text; worker.RunWorkerAsync(); } } void worker_DoWork(object sender, DoWorkEventArgs e) { try { serviceHost = new ServiceHost(typeof(Service1)); if (serviceHost.State != CommunicationState.Opened) { serviceHost.Open(); } e.Result = "正常"; } catch (Exception ex) { e.Result = ex.Message; } } void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Result != null) { if (e.Result.ToString() == "正常") { tssTips.Text = "服務正在進行偵聽......"; } else { tssTips.Text = string.Format("錯誤:{0}", e.Result); } lblTips.Text = tssTips.Text; } } ........................... } }
當然為了防止Winform程序被不小心關閉,可以添加托盤代碼,把程序縮小到托盤圖標裏面。
5、 WCF服務的Windows 服務程序寄宿
這種方式的服務寄宿,和IIS一樣有一個一樣的優點,系統啟動後,WCF服務也會跟著啟動了,不用人工幹預,也是一種較好的寄宿方式。
為了實現這種方式的寄宿,我們創建一個控制臺程序,然後添加響應的Window服務和安裝程序類
然後在服務類啟動裏面添加WCF的寄宿代碼,如下所示。
public class ServiceManager : ServiceBase { private static object syncRoot = new Object();//同步鎖 private ServiceHost serviceHost = null; //寄宿服務對象 public ServiceManager() { this.ServiceName = Constants.ServiceName; } /// <summary> /// 設置具體的操作,以便服務可以執行它的工作。 /// </summary> protected override void OnStart(string[] args) { try { serviceHost = new ServiceHost(typeof(Service1)); if (serviceHost.State != CommunicationState.Opened) { serviceHost.Open(); } } catch (Exception ex) { LogTextHelper.Error(ex); } LogTextHelper.Info(Constants.ServiceName + DateTime.Now.ToShortTimeString() + "已成功調用了服務一次。"); LogTextHelper.Info(Constants.ServiceName + "已成功啟動。"); }
為了實現通過該控制臺程序實現參數化安裝和卸載服務,我們需要攔截控制臺的參數,並進行相應的操作,如下所示。
/// <summary> /// 應用程序的主入口點。 /// </summary> [STAThread] static void Main(string[] args) { ServiceController service = new ServiceController(Constants.ServiceName); // 運行服務 if (args.Length == 0) { ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new ServiceManager() }; ServiceBase.Run(ServicesToRun); } else if (args[0].ToLower() == "/i" || args[0].ToLower() == "-i") { #region 安裝服務 if (!ServiceIsExisted(Constants.ServiceName)) { try { string[] cmdline = { }; string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location; TransactedInstaller transactedInstaller = new TransactedInstaller(); AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline); transactedInstaller.Installers.Add(assemblyInstaller); transactedInstaller.Install(new System.Collections.Hashtable()); TimeSpan timeout = TimeSpan.FromMilliseconds(1000 * 10); service.Start(); service.WaitForStatus(ServiceControllerStatus.Running, timeout); } catch (Exception ex) { LogTextHelper.Info(ex); throw; } } #endregion } else if (args[0].ToLower() == "/u" || args[0].ToLower() == "-u") { #region 刪除服務 try { if (ServiceIsExisted(Constants.ServiceName)) { string[] cmdline = { }; string serviceFileName = System.Reflection.Assembly.GetExecutingAssembly().Location; TransactedInstaller transactedInstaller = new TransactedInstaller(); AssemblyInstaller assemblyInstaller = new AssemblyInstaller(serviceFileName, cmdline); transactedInstaller.Installers.Add(assemblyInstaller); transactedInstaller.Uninstall(null); } } catch (Exception ex) { LogTextHelper.Info(ex); throw; } #endregion } }
編譯程序成功後,我們添加兩個批處理的DOS腳本來實現執行程序的自動安裝和卸載,如下所示。
安裝腳本
"WcfService_HostWinService.exe" -i pause
卸載腳本
"WcfService_HostWinService.exe" -u pause
順利執行腳本後,服務列表裏面就增加一個服務項目了。
卸載操作,直接執行腳本就會卸載服務,非常方便哦。
6、 WCF服務的Web寄宿
當然,除了以上幾種方式,這種以WCF服務庫的方式,也可以在Web方式進行寄宿(IIS方式),這種方式更簡單,添加一個後綴名的svc的文件,只需要一行代碼即可,如下所示。
7、 使WCF服務支持GET方式調用
有時候,我們為了需要,可能通過一個小程序發布一個服務,然後供其他程序進行調用,可能是Web,也可以是Winform,但是我們是想提供一個基於HTTP,GET或者POST方式來實現接口的調用的,例如,提供一個JSON格式或者文本格式的內容返回操作。
如果是整合在Winform裏面,那麽我們在Winform裏面添加一個WCF的項,修改裏面的代碼就可以了,如下所示。
首先要在使用GET方式的WCF服務接口的添加說明。如果是POS方式,增加設置有點不同([WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)])。
namespace WcfServiceForWinform { [ServiceContract] public interface IService1 { [OperationContract] void DoWork(); [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json)] string GetData(int value); } }
第二,在實現類裏面添加相應的設置
namespace WcfServiceForWinform { [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class Service1 : IService1 { public void DoWork() { } public string GetData(int value) { return string.Format("You entered: {0}", value); } } }
配置文件如下所示,顏色標註特別的要註意:
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="true"/> </system.web> <system.serviceModel> <services> <service name="WcfServiceForWinform.Service1" behaviorConfiguration="ServiceConfig"> <endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBindingWithJsonP" behaviorConfiguration="webHttpBehavior" contract="WcfServiceForWinform.IService1"> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="http://localhost:9000/Service1/" /> </baseAddresses> </host> </service> </services> <bindings> <webHttpBinding> <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" /> </webHttpBinding> </bindings> <behaviors> <endpointBehaviors> <behavior name="webHttpBehavior"> <webHttp/> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior name="ServiceConfig"> <serviceMetadata httpGetEnabled="True" policyVersion="Policy15"/> <serviceDebug includeExceptionDetailInFaults="False"/> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> </system.serviceModel> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> </startup> </configuration>
運行Winform程序,啟動了WCF服務後,我們可以在瀏覽器(Chrome)上進行操作,如下結果所示。
從上圖我們可以看到,這個通過Winform啟動起來的WCF服務,連接也能通過GET方式進行接口調用了,接口可以通過參數進行傳遞,對於一些方便傳輸數據的接口如JSON接口,就是一種非常方便的調用了。
微軟 WCF的幾種寄宿方式,寄宿IIS、寄宿winform、寄宿控制臺、寄宿Windows服務