Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе показаны основные шаги по созданию методов программирования, использующих двусторонний дуплексный контракт. Дуплексный контракт позволяет клиентам и серверам независимо обмениваться вызовами, так что обе стороны могут инициировать вызовы друг к другу. Дуплексный контракт — это один из трех шаблонов сообщений, доступных службам Windows Communication Foundation (WCF). Остальные два шаблона сообщений: односторонний и запрос-ответ. Дуплексный контракт состоит из двух односторонних контрактов между клиентом и сервером и не требует сопоставления вызовов метода. Используйте этот контракт, когда служба должна опрашивать клиент для получения дополнительных сведений или явно генерировать события на клиенте. Дополнительные сведения о создании клиентского приложения для дуплексного контракта см. в статье "Практическое руководство. Доступ к службам с помощью дуплексного контракта". Рабочий пример см. в примере Duplex .
Создание дуплексного контракта
Создайте интерфейс, который обеспечивает работу серверной стороны в дуплексном контракте.
Примените класс ServiceContractAttribute к интерфейсу.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required, CallbackContract=typeof(ICalculatorDuplexCallback))] public interface ICalculatorDuplex { [OperationContract(IsOneWay=true)] void Clear(); [OperationContract(IsOneWay = true)] void AddTo(double n); [OperationContract(IsOneWay = true)] void SubtractFrom(double n); [OperationContract(IsOneWay = true)] void MultiplyBy(double n); [OperationContract(IsOneWay = true)] void DivideBy(double n); }<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required, _ CallbackContract:=GetType(ICalculatorDuplexCallback))> _ Public Interface ICalculatorDuplex <OperationContract(IsOneWay:=True)> _ Sub Clear() <OperationContract(IsOneWay:=True)> _ Sub AddTo(ByVal n As Double) <OperationContract(IsOneWay:=True)> _ Sub SubtractFrom(ByVal n As Double) <OperationContract(IsOneWay:=True)> _ Sub MultiplyBy(ByVal n As Double) <OperationContract(IsOneWay:=True)> _ Sub DivideBy(ByVal n As Double) End InterfaceОбъявите подписи метода в интерфейсе.
Примените OperationContractAttribute класс к каждой подписи метода, которая должна быть частью открытого контракта.
Создайте интерфейс обратного вызова, определяющий набор операций, которые служба может вызвать на клиенте.
public interface ICalculatorDuplexCallback { [OperationContract(IsOneWay = true)] void Equals(double result); [OperationContract(IsOneWay = true)] void Equation(string eqn); }Public Interface ICalculatorDuplexCallback <OperationContract(IsOneWay:=True)> _ Sub Equals(ByVal result As Double) <OperationContract(IsOneWay:=True)> _ Sub Equation(ByVal eqn As String) end interfaceОбъявите подписи метода в интерфейсе обратного вызова.
Примените OperationContractAttribute класс к каждой подписи метода, которая должна быть частью открытого контракта.
Свяжите два интерфейса в дуплексный контракт, задав в основном интерфейсе свойство CallbackContract типу интерфейса обратного вызова.
Вызов методов на клиенте
В реализации основного контракта сервиса объявите переменную для интерфейса обратного вызова.
Установите переменную на ссылку объекта, возвращаемую методом GetCallbackChannel класса OperationContext.
ICalculatorDuplexCallback callback = null;Dim callback As ICalculatorDuplexCallbackcallback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();callback = OperationContext.Current.GetCallbackChannel(Of ICalculatorDuplexCallback)()Вызов методов, определенных интерфейсом обратного вызова.
Пример
В следующем примере кода демонстрируется дуплексное взаимодействие. Договор на обслуживание включает операции перемещения вперед и назад. Контракт клиента содержит служебную операцию для отчетности о его местонахождении.
// Define a duplex service contract.
// A duplex contract consists of two interfaces.
// The primary interface is used to send messages from client to service.
// The callback interface is used to send messages from service back to client.
// ICalculatorDuplex allows one to perform multiple operations on a running result.
// The result is sent back after each operation on the ICalculatorCallback interface.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required,
CallbackContract=typeof(ICalculatorDuplexCallback))]
public interface ICalculatorDuplex
{
[OperationContract(IsOneWay=true)]
void Clear();
[OperationContract(IsOneWay = true)]
void AddTo(double n);
[OperationContract(IsOneWay = true)]
void SubtractFrom(double n);
[OperationContract(IsOneWay = true)]
void MultiplyBy(double n);
[OperationContract(IsOneWay = true)]
void DivideBy(double n);
}
// The callback interface is used to send messages from service back to client.
// The Equals operation will return the current result after each operation.
// The Equation operation will return the complete equation after Clear() is called.
public interface ICalculatorDuplexCallback
{
[OperationContract(IsOneWay = true)]
void Equals(double result);
[OperationContract(IsOneWay = true)]
void Equation(string eqn);
}
// Service class which implements a duplex service contract.
// Use an InstanceContextMode of PerSession to store the result
// An instance of the service will be bound to each duplex session
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class CalculatorService : ICalculatorDuplex
{
double result;
string equation;
ICalculatorDuplexCallback callback = null;
public CalculatorService()
{
result = 0.0D;
equation = result.ToString();
callback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();
}
public void Clear()
{
callback.Equation(equation + " = " + result.ToString());
result = 0.0D;
equation = result.ToString();
}
public void AddTo(double n)
{
result += n;
equation += " + " + n.ToString();
callback.Equals(result);
}
public void SubtractFrom(double n)
{
result -= n;
equation += " - " + n.ToString();
callback.Equals(result);
}
public void MultiplyBy(double n)
{
result *= n;
equation += " * " + n.ToString();
callback.Equals(result);
}
public void DivideBy(double n)
{
result /= n;
equation += " / " + n.ToString();
callback.Equals(result);
}
}
' Define a duplex service contract.
' A duplex contract consists of two interfaces.
' The primary interface is used to send messages from client to service.
' The callback interface is used to send messages from service back to client.
' ICalculatorDuplex allows one to perform multiple operations on a running result.
' The result is sent back after each operation on the ICalculatorCallback interface.
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples", SessionMode:=SessionMode.Required, _
CallbackContract:=GetType(ICalculatorDuplexCallback))> _
Public Interface ICalculatorDuplex
<OperationContract(IsOneWay:=True)> _
Sub Clear()
<OperationContract(IsOneWay:=True)> _
Sub AddTo(ByVal n As Double)
<OperationContract(IsOneWay:=True)> _
Sub SubtractFrom(ByVal n As Double)
<OperationContract(IsOneWay:=True)> _
Sub MultiplyBy(ByVal n As Double)
<OperationContract(IsOneWay:=True)> _
Sub DivideBy(ByVal n As Double)
End Interface
' The callback interface is used to send messages from service back to client.
' The Equals operation will return the current result after each operation.
' The Equation operation will return the complete equation after Clear() is called.
Public Interface ICalculatorDuplexCallback
<OperationContract(IsOneWay:=True)> _
Sub Equals(ByVal result As Double)
<OperationContract(IsOneWay:=True)> _
Sub Equation(ByVal eqn As String)
end interface
' Service class which implements a duplex service contract.
' Use an InstanceContextMode of PerSession to store the result
' An instance of the service will be bound to each duplex session
<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession)> _
Public Class CalculatorService
Implements ICalculatorDuplex
Dim result As Double
Dim equation As String
Dim callback As ICalculatorDuplexCallback
Public Sub New()
result = 0D
equation = result.ToString()
callback = OperationContext.Current.GetCallbackChannel(Of ICalculatorDuplexCallback)()
End Sub
Public Sub AddTo(ByVal n As Double) Implements ICalculatorDuplex.AddTo
result += n
equation += " + " + n.ToString()
callback.Equals(result)
End Sub
Public Sub Clear() Implements ICalculatorDuplex.Clear
callback.Equation(equation + " = " + result.ToString())
result = 0D
equation = result.ToString()
End Sub
Public Sub DivideBy(ByVal n As Double) Implements ICalculatorDuplex.DivideBy
result /= n
equation += " / " + n.ToString()
callback.Equals(result)
End Sub
Public Sub MultiplyBy(ByVal n As Double) Implements ICalculatorDuplex.MultiplyBy
result *= n
equation += " * " + n.ToString()
callback.Equals(result)
End Sub
Public Sub SubtractFrom(ByVal n As Double) Implements ICalculatorDuplex.SubtractFrom
result -= n
equation += " - " + n.ToString()
callback.Equals(result)
End Sub
End Class
ServiceContractAttribute Применение атрибутов OperationContractAttribute позволяет автоматически генерирование определений контракта службы на языке описания веб-служб (WSDL).
Используйте средство служебной программы метаданных ServiceModel (Svcutil.exe) для получения документа WSDL и (необязательно) кода и конфигурации клиента.
Конечные точки, предоставляющие дуплексные службы, должны быть защищены. Когда служба получает дуплексное сообщение, она смотрит на ReplyTo во входящем сообщении, чтобы определить, куда отправлять ответ. Если канал не защищен, то ненадежный клиент может отправить вредоносное сообщение с указанием ReplyTo целевой машины, что может вызвать отказ в обслуживании целевой машины. При регулярных запросах-ответах это не проблема, так как ReplyTo игнорируется, и ответ отправляется на канал, по которому поступило исходное сообщение.