作法:在 WAS 中裝載 WCF 服務
本主題概要說明建立 Windows Process Activation Services (又稱為 WAS) 所裝載的 Windows Communication Foundation (WCF) 服務時,必要的基本步驟。 WAS 是新的處理序啟用服務,其為一般化的 Internet Information Services (IIS) 功能,與非 HTTP 傳輸通訊協定搭配使用。 WCF 使用接聽程式配接器介面來與透過 WCF 所支援的非 HTTP 通訊協定 (例如 TCP、具名管道和訊息佇列) 接收的啟用要求進行通訊。
這個裝載選項要求 WAS 啟用元件必須正確安裝與設定,但不要求將任何裝載程式碼撰寫為應用程式的一部分。 如需詳細瞭解如何安裝和設定 WAS,請參閱如何安裝和設定 WCF 啟用元件。
警告
如果 Web 伺服器的要求處理管線設定為「傳統」模式,就不支援 WAS 啟動。 若要使用 WAS 啟動,Web 伺服器的要求處理管線就必須設定為「整合」模式。
透過 WAS 裝載 WCF 服務時,標準繫結的使用方式與平常一樣。 但是,當透過 NetTcpBinding 和 NetNamedPipeBinding 來設定 WAS 裝載的服務時,就必須滿足下列限制。 當不同的端點使用同一個傳輸,繫結設定必須符合下列七項屬性:
ConnectionBufferSize
ChannelInitializationTimeout
MaxPendingConnections
MaxOutputDelay
MaxPendingAccepts
ConnectionPoolSettings.IdleTimeout
ConnectionPoolSettings.MaxOutboundConnectionsPerEndpoint
否則,先初始化的端點一律直接決定這些屬性的值,而稍後新增的端點則會在這些屬性值未符合上述設定值時擲回 ServiceActivationException。
如需此範例的來源複本,請參閱 TCP 啟用。
若要建立 WAS 裝載的基本服務
定義服務類型的服務合約。
[ServiceContract] public interface ICalculator { [OperationContract] double Add(double n1, double n2); [OperationContract] double Subtract(double n1, double n2); [OperationContract] double Multiply(double n1, double n2); [OperationContract] double Divide(double n1, double n2); }
在服務類別中實作服務合約。 請注意,服務的實作內並未指定位址或繫結資訊。 同時,您不需要撰寫可從組態檔擷取該資訊的程式碼。
public class CalculatorService : ICalculator { public double Add(double n1, double n2) { return n1 + n2; } public double Subtract(double n1, double n2) { return n1 - n2; } public double Multiply(double n1, double n2) { return n1 * n2; } public double Divide(double n1, double n2) { return n1 / n2; } }
建立 Web.config 檔案,定義 NetTcpBinding 端點要使用的
CalculatorService
繫結。<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <bindings> <netTcpBinding> <binding portSharingEnabled="true"> <security mode="None" /> </binding> </netTcpBinding> </bindings> </system.serviceModel> </configuration>
建立包含下列程式碼的 Service.svc 檔案。
<%@ServiceHost language=c# Service="CalculatorService" %>
將 Service.svc 檔放入您的 IIS 虛擬目錄中。
若要建立用戶端來使用服務
從命令列使用 ServiceModel 中繼資料公用程式工具 (Svcutil.exe),可從服務中繼資料產生程式碼。
Svcutil.exe <service's Metadata Exchange (MEX) address or HTTP GET address>
所產生的用戶端會包含
ICalculator
介面,其中定義了用戶端實作所必須滿足的服務合約。//Generated interface defining the ICalculator contract [System.ServiceModel.ServiceContractAttribute( Namespace="http://Microsoft.ServiceModel.Samples", ConfigurationName="Microsoft.ServiceModel.Samples.ICalculator")] public interface ICalculator { [System.ServiceModel.OperationContractAttribute( Action="http://Microsoft.ServiceModel.Samples/ICalculator/Add", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/AddResponse")] double Add(double n1, double n2); [System.ServiceModel.OperationContractAttribute( Action="http://Microsoft.ServiceModel.Samples/ICalculator/Subtract", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/SubtractResponse")] double Subtract(double n1, double n2); [System.ServiceModel.OperationContractAttribute( Action="http://Microsoft.ServiceModel.Samples/ICalculator/Multiply", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/MultiplyResponse")] double Multiply(double n1, double n2); [System.ServiceModel.OperationContractAttribute( Action="http://Microsoft.ServiceModel.Samples/ICalculator/Divide", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/DivideResponse")] double Divide(double n1, double n2); }
產生的用戶端應用程式也包含
ClientCalculator
的實作。 請注意,服務的實作內部並未指定位址和繫結資訊。 同時,您不需要撰寫可從組態檔擷取該資訊的程式碼。// Implementation of the CalculatorClient public partial class CalculatorClient : System.ServiceModel.ClientBase<Microsoft.ServiceModel.Samples.ICalculator>, Microsoft.ServiceModel.Samples.ICalculator { public CalculatorClient() { } public CalculatorClient(string endpointConfigurationName) : base(endpointConfigurationName) { } public CalculatorClient(string endpointConfigurationName, string remoteAddress) : base(endpointConfigurationName, remoteAddress) { } public CalculatorClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : base(endpointConfigurationName, remoteAddress) { } public CalculatorClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : base(binding, remoteAddress) { } public double Add(double n1, double n2) { return base.Channel.Add(n1, n2); } public double Subtract(double n1, double n2) { return base.Channel.Subtract(n1, n2); } public double Multiply(double n1, double n2) { return base.Channel.Multiply(n1, n2); } public double Divide(double n1, double n2) { return base.Channel.Divide(n1, n2); } }
使用 NetTcpBinding 的用戶端組態也是由 Svcutil.exe 所產生的。 使用 Visual Studio 時,此檔案應該命名為 App.config。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <bindings> <netTcpBinding> <binding name="NetTcpBinding_ICalculator"> <security mode="None"/> </binding> </netTcpBinding> </bindings> <client> <endpoint address="net.tcp://localhost/servicemodelsamples/service.svc" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ICalculator" contract="ICalculator" name="NetTcpBinding_ICalculator" /> </client> </system.serviceModel> </configuration>
在應用程式中建立
ClientCalculator
的執行個體,然後呼叫服務作業。//Client implementation code. class Client { static void Main() { // Create a client with given client endpoint configuration CalculatorClient client = new CalculatorClient(); // Call the Add service operation. double value1 = 100.00D; double value2 = 15.99D; double result = client.Add(value1, value2); Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result); // Call the Subtract service operation. value1 = 145.00D; value2 = 76.54D; result = client.Subtract(value1, value2); Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result); // Call the Multiply service operation. value1 = 9.00D; value2 = 81.25D; result = client.Multiply(value1, value2); Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result); // Call the Divide service operation. value1 = 22.00D; value2 = 7.00D; result = client.Divide(value1, value2); Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result); //Closing the client gracefully closes the connection and cleans up resources client.Close(); Console.WriteLine(); Console.WriteLine("Press <ENTER> to terminate client."); Console.ReadLine(); } }
請編譯並執行用戶端。