所有與 Windows Communication Foundation (WCF) 服務的通訊都會透過其端點進行。 每個 ServiceEndpoint 都包含、 AddressBinding和 Contract。 合約規定哪些作業可用。 系結會指定如何與服務通訊,而位址會指定尋找服務的位置。 每個端點都必須有唯一的位址。 端點位址是由 EndpointAddress 類別所代表,其中包含代表服務地址的統一資源識別元(URI),代表服務 Identity的安全性識別,以及選擇性 Headers的集合。 選擇性標頭提供更詳細的尋址資訊,以識別或與端點互動。 例如,標頭可以指出如何處理傳入訊息、端點應該傳送回復訊息的位置,或當有多個實例可用時,要用來處理來自特定使用者之傳入訊息的服務實例。
端點地址的定義
在 WCF 中,EndpointAddress 被建模為端點參考(EPR),如 WS-Addressing 標準中所定義。
大部分傳輸的位址 URI 有四個部分。 例如,此 URI http://www.fabrikam.com:322/mathservice.svc/secureEndpoint 具有下列四個部分:
通訊協定:http:
機器:
www.fabrikam.com(選擇性)埠:322
路徑:/mathservice.svc/secureEndpoint
EPR 模型的一部分是每個端點參考可以攜帶一些參考參數,以新增額外的識別資訊。 在 WCF 中,這些參考參數會模型化為 類別的 AddressHeader 實例。
您可以透過程式碼命令式指定或透過組態宣告式指定服務的端點位址。 在程式代碼中定義端點通常並不實用,因為已部署服務的系結和位址通常與開發服務時所使用的端點不同。 一般而言,使用組態而非程式代碼來定義服務端點會比較實用。 將系結和尋址資訊保留在程序代碼中,可讓它們變更,而不需要重新編譯和重新部署應用程式。 如果未在程式代碼或組態中指定任何端點,則運行時間會在服務所實作之每個合約的每個基位址上新增一個預設端點。
有兩種方式可以在 WCF 中指定服務的端點位址。 您可以為與服務相關聯的每個端點指定絕對位址,也可以為服務的 提供基地址,然後針對與此基地址 ServiceHost 相對定義的每個端點指定位址。 您可以使用這些程式,在組態或程式代碼中指定服務的端點位址。 如果您未指定相對地址,服務會使用基位址。 您也可以有多個服務的基位址,但每個服務只允許每個傳輸的一個基位址。 如果您有多個端點,且每個端點都設定為不同的系結,其位址必須是唯一的。 使用相同系結但不同合約的端點可以使用相同的位址。
使用 IIS 裝載時,您不會自行管理 ServiceHost 實例。 在 IIS 中裝載時,基位址一律是服務 .svc 檔案中指定的位址。 因此,您必須針對 IIS 託管的服務入口使用相對位址。 提供完整定義的端點位址可能會導致服務部署發生錯誤。 如需詳細資訊,請參閱 部署因特網資訊 Services-Hosted WCF 服務。
在組態中定義端點位址
若要在組態檔中定義端點,請使用 <endpoint> 元素。
<configuration>
<system.serviceModel>
<services>
<service name="UE.Samples.HelloService"
behaviorConfiguration="HelloServiceBehavior">
<endpoint address="/Address1"
binding="basicHttpBinding"
contract="UE.Samples.IHello"/>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="HelloServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
當Open方法被呼叫時(也就是當主控應用程式嘗試啟動服務時),系統會尋找<服務>元素,其名稱屬性指定 "UE.Samples.HelloService"。 <如果找到服務>項目,系統會載入指定的類別,並使用組態檔中提供的端點定義來建立端點。 此機制可讓您使用兩行程式代碼載入和啟動服務,同時將系結和尋址資訊保留在程式代碼外。 這種方法的優點是可以進行這些變更,而不需要重新編譯或重新部署應用程式。
選擇性標頭會在<headers>中宣告。 以下是用來在組態檔中指定服務端點的元素範例,可區別兩個標頭:“Gold” 用戶端來自http://tempuri1.org/以及 “Standard” 用戶端來自http://tempuri2.org/。 呼叫此服務的用戶端在其組態檔中必須具有適當的 <標頭> 。
<configuration>
<system.serviceModel>
<services>
<service name="UE.Samples.HelloService"
behaviorConfiguration="HelloServiceBehavior">
<endpoint address="/Address1"
binding="basicHttpBinding"
contract="UE.Samples.IHello">
<headers>
<Member xmlns="http://tempuri1.org/">Gold</Member>
</headers>
</endpoint>
<endpoint address="/Address2"
binding="basicHttpBinding"
contract="UE.Samples.IHello">
<headers>
<Member xmlns="http://tempuri2.org/">Silver</Member>
</headers>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="HelloServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
標頭也可以在個別訊息上設定,而不是端點上的所有訊息(如先前所示)。 這是使用 OperationContextScope 在用戶端應用程式中建立新的內容,將自定義標頭新增至傳出訊息,如下列範例所示。
SampleServiceClient wcfClient = new SampleServiceClient(new InstanceContext(this));
try
{
using (OperationContextScope scope = new OperationContextScope(wcfClient.InnerChannel))
{
MessageHeader header
= MessageHeader.CreateHeader(
"Service-Bound-CustomHeader",
"http://Microsoft.WCF.Documentation",
"Custom Happy Value."
);
OperationContext.Current.OutgoingMessageHeaders.Add(header);
// Making calls.
Console.WriteLine("Enter the greeting to send: ");
string greeting = Console.ReadLine();
//Console.ReadLine();
header = MessageHeader.CreateHeader(
"Service-Bound-OneWayHeader",
"http://Microsoft.WCF.Documentation",
"Different Happy Value."
);
OperationContext.Current.OutgoingMessageHeaders.Add(header);
// One-way
wcfClient.Push(greeting);
this.wait.WaitOne();
// Done with service.
wcfClient.Close();
Console.WriteLine("Done!");
Console.ReadLine();
}
}
catch (TimeoutException timeProblem)
{
Console.WriteLine("The service operation timed out. " + timeProblem.Message);
Console.ReadLine();
wcfClient.Abort();
}
catch (CommunicationException commProblem)
{
Console.WriteLine("There was a communication problem. " + commProblem.Message);
Console.ReadLine();
wcfClient.Abort();
}
Dim wcfClient As New SampleServiceClient(New InstanceContext(Me))
Try
Using scope As New OperationContextScope(wcfClient.InnerChannel)
Dim header As MessageHeader = MessageHeader.CreateHeader("Service-Bound-CustomHeader", _
"http://Microsoft.WCF.Documentation", "Custom Happy Value.")
OperationContext.Current.OutgoingMessageHeaders.Add(header)
' Making calls.
Console.WriteLine("Enter the greeting to send: ")
Dim greeting As String = Console.ReadLine()
'Console.ReadLine();
header = MessageHeader.CreateHeader("Service-Bound-OneWayHeader", _
"http://Microsoft.WCF.Documentation", "Different Happy Value.")
OperationContext.Current.OutgoingMessageHeaders.Add(header)
' One-way
wcfClient.Push(greeting)
Me.wait.WaitOne()
' Done with service.
wcfClient.Close()
Console.WriteLine("Done!")
Console.ReadLine()
End Using
Catch timeProblem As TimeoutException
Console.WriteLine("The service operation timed out. " & timeProblem.Message)
Console.ReadLine()
wcfClient.Abort()
Catch commProblem As CommunicationException
Console.WriteLine("There was a communication problem. " & commProblem.Message)
Console.ReadLine()
wcfClient.Abort()
End Try
元數據中的端點位址
端點位址會以 Web 服務描述語言(WSDL)表示為對應端點的元素EndpointReference內的 WS-Addressingwsdl:port(EPR)元素。 EPR 包含端點的位址以及任何位址屬性。 請注意,內的 wsdl:port EPR 會取代 soap:Address ,如下列範例所示。
在程式代碼中定義端點位址
您可以使用 類別在程式代碼 EndpointAddress 中建立端點位址。 為端點位址指定的 URI 可以是完全合格路徑或相對於服務基底位址的路徑。 下列程式代碼說明如何建立 類別的 EndpointAddress 實例,並將它新增至 ServiceHost 裝載服務的實例。
下列範例示範如何在程式碼中指定完整的端點位址。
Uri baseAddress = new Uri("http://localhost:8000/HelloService");
string address = "http://localhost:8000/HelloService/MyService";
using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), address);
serviceHost.Open();
Console.WriteLine("Press <enter> to terminate service");
Console.ReadLine();
serviceHost.Close();
}
下列範例示範如何將相對位址 (“MyService”) 新增至服務主機的基位址。
Uri baseAddress = new Uri("http://localhost:8000/HelloService");
using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), "MyService");
serviceHost.Open();
Console.WriteLine("Press <enter> to terminate service");
Console.ReadLine();
serviceHost.Close();
}
備註
在服務應用程式中的ServiceDescription屬性,在OnOpening上的ServiceHostBase方法之後,不得被修改。 某些成員,例如Credentials屬性和AddServiceEndpoint方法,在ServiceHostBase和ServiceHost上,如果在該點之後被修改,則會擲回例外狀況。 其他人則允許您修改它們,但結果未定義。
同樣地,在用戶端上,在對ServiceEndpoint呼叫OnOpening之後,不得修改ChannelFactory的值。 Credentials屬性會在該點之後修改時擲回例外狀況。 其他用戶端描述值可以修改而不發生錯誤,但結果未定義。
無論是針對服務還是客戶端,建議您先修改描述,再呼叫 Open。
使用預設端點
如果未在程式代碼或組態中指定任何端點,則運行時間會在服務所實作之每個服務合約的每個基位址上新增一個預設端點,以提供預設端點。 基位址可以在程式碼或組態中指定,當在 Open 上呼叫 ServiceHost 時會新增預設端點。
如果明確提供端點,在呼叫 AddDefaultEndpoints 之前,仍然可以先在 ServiceHost 上呼叫 Open 來新增預設端點。 如需預設端點、系結和行為的詳細資訊,請參閱 WCF 服務的 簡化組態 和 簡化組態。