Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Все взаимодействие со службой Windows Communication Foundation (WCF) осуществляется через конечные точки. Каждый ServiceEndpoint содержит Address, a Bindingи a 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 самостоятельно. Базовый адрес всегда является адресом, указанным в SVC-файле службы при размещении в IIS. Поэтому необходимо использовать относительные адреса конечных точек служб, размещённых на IIS. Предоставление полностью квалифицированного адреса конечной точки может привести к ошибкам в развертывании службы. Дополнительные сведения см. в статье о развертывании службы WCF Internet Information Services-Hosted.
Определение адресов конечных точек в конфигурации
Чтобы определить конечную точку в файле конфигурации, используйте элемент конечной< точки>.
<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". <Если элемент службы> найден, система загружает указанный класс и создает конечные точки с помощью определений конечных точек, указанных в файле конфигурации. Этот механизм позволяет загружать и запускать службу, используя всего две строки кода, при этом исключая информацию о привязке и адресации из вашего кода. Преимуществом этого подхода является то, что эти изменения можно вносить без необходимости повторно компилировать или повторно развертывать приложение.
Необязательные заголовки объявляются в <заголовках>. Ниже приведен пример элементов, используемых для указания конечных точек службы в файле конфигурации, который различает два заголовка: "Gold" для клиентов из http://tempuri1.org/ и "Стандартный" для клиентов из 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
Адрес конечной точки в метаданных
Адрес конечной точки представлен в языке описания веб-служб (WSDL) как элемент WS-Addressing EndpointReference (EPR) внутри соответствующего элемента конечной точки wsdl:port . EPR содержит адрес конечной точки, а также любые свойства адреса. Обратите внимание, что EPR внутри wsdl:port заменяет 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.
Если конечные точки явно предоставляются, конечные точки по умолчанию можно добавлять, вызывая AddDefaultEndpointsServiceHost перед вызовом Open. Дополнительные сведения о конечных точках, привязках и поведении по умолчанию см. в статье "Упрощенная конфигурация " и "Упрощенная конфигурация" для служб WCF.