Anmerkung
Der Zugriff auf diese Seite erfordert eine Genehmigung. Du kannst versuchen, dich anzumelden oder die Verzeichnisse zu wechseln.
Der Zugriff auf diese Seite erfordert eine Genehmigung. Du kannst versuchen , die Verzeichnisse zu wechseln.
Ein Duplexdienstvertrag ist ein Nachrichtenaustauschmuster, in dem beide Endpunkte Nachrichten unabhängig voneinander senden können. Ein Duplexdienst kann daher Nachrichten zurück an den Clientendpunkt senden und ereignisähnliches Verhalten bereitstellen. Duplexkommunikation tritt auf, wenn ein Client eine Verbindung mit einem Dienst herstellt und den Dienst mit einem Kanal bereitstellt, in dem der Dienst Nachrichten zurück an den Client senden kann. Beachten Sie, dass das ereignisähnliche Verhalten von Duplexdiensten nur innerhalb einer Sitzung funktioniert.
Zum Erstellen eines Duplexvertrags erstellen Sie ein Schnittstellenpaar. Die erste ist die Dienstvertragsschnittstelle, die die Vorgänge beschreibt, die ein Client aufrufen kann. Dieser Dienstvertrag muss einen Rückrufvertrag in der ServiceContractAttribute.CallbackContract Eigenschaft angeben. Der Rückrufvertrag ist die Schnittstelle, die die Vorgänge definiert, die der Dienst auf dem Clientendpunkt aufrufen kann. Ein Duplexvertrag erfordert keine Sitzung, obwohl die vom System bereitgestellten Duplexbindungen sie nutzen.
Im Folgenden sehen Sie ein Beispiel für einen Duplex-Vertrag.
[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);
}
public interface ICalculatorDuplexCallback
{
[OperationContract(IsOneWay = true)]
void Equals(double result);
[OperationContract(IsOneWay = true)]
void Equation(string eqn);
}
<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
Public Interface ICalculatorDuplexCallback
<OperationContract(IsOneWay:=True)> _
Sub Equals(ByVal result As Double)
<OperationContract(IsOneWay:=True)> _
Sub Equation(ByVal eqn As String)
End Interface
Die CalculatorService Klasse implementiert die primäre ICalculatorDuplex Schnittstelle. Der Dienst verwendet den PerSession Instanzmodus, um das Ergebnis für jede Sitzung beizubehalten. Die private Callback-Eigenschaft greift auf den Rückrufkanal zu, der zum Client führt. Der Dienst verwendet den Rückruf zum Senden von Nachrichten an den Client über die Rückrufschnittstelle, wie im folgenden Beispielcode gezeigt.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class CalculatorService : ICalculatorDuplex
{
double result = 0.0D;
string equation;
public CalculatorService()
{
equation = result.ToString();
}
public void Clear()
{
Callback.Equation(equation + " = " + result.ToString());
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);
}
ICalculatorDuplexCallback Callback
{
get
{
return OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();
}
}
}
<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession)> _
Public Class CalculatorService
Implements ICalculatorDuplex
Private result As Double = 0.0R
Private equation As String
Public Sub New()
equation = result.ToString()
End Sub
Public Sub Clear() Implements ICalculatorDuplex.Clear
Callback.Equation(equation & " = " & result.ToString())
equation = result.ToString()
End Sub
Public Sub AddTo(ByVal n As Double) Implements ICalculatorDuplex.AddTo
result += n
equation &= " + " & n.ToString()
CType(Callback, Object).Equals(result)
End Sub
Public Sub SubtractFrom(ByVal n As Double) Implements ICalculatorDuplex.SubtractFrom
result -= n
equation &= " - " & n.ToString()
CType(Callback, Object).Equals(result)
End Sub
Public Sub MultiplyBy(ByVal n As Double) Implements ICalculatorDuplex.MultiplyBy
result *= n
equation &= " * " & n.ToString()
CType(Callback, Object).Equals(result)
End Sub
Public Sub DivideBy(ByVal n As Double) Implements ICalculatorDuplex.DivideBy
result /= n
equation &= " / " & n.ToString()
CType(Callback, Object).Equals(result)
End Sub
Private ReadOnly Property Callback() As ICalculatorDuplexCallback
Get
Return OperationContext.Current.GetCallbackChannel(Of ICalculatorDuplexCallback)()
End Get
End Property
End Class
Der Client muss eine Klasse bereitstellen, die die Rückrufschnittstelle des Duplex-Vertrags implementiert, um Nachrichten vom Dienst zu empfangen. Der folgende Beispielcode zeigt eine CallbackHandler Klasse, die die ICalculatorDuplexCallback Schnittstelle implementiert.
public class CallbackHandler : ICalculatorDuplexCallback
{
public void Equals(double result)
{
Console.WriteLine($"Equals({result})");
}
public void Equation(string eqn)
{
Console.WriteLine($"Equation({eqn})");
}
}
Public Class CallbackHandler
Implements ICalculatorDuplexCallback
Public Overridable Shadows Sub Equals(ByVal result As Double) Implements ICalculatorDuplexCallback.Equals
Console.WriteLine("Equals({0})", result)
End Sub
Public Sub Equation(ByVal eqn As String) Implements ICalculatorDuplexCallback.Equation
Console.WriteLine("Equation({0})", eqn)
End Sub
End Class
Der WCF-Client, der für einen Duplex-Vertrag generiert wird, erfordert, dass beim Bau eine InstanceContext Klasse bereitgestellt wird. Diese InstanceContext Klasse wird als Website für ein Objekt verwendet, das die Rückrufschnittstelle implementiert und Nachrichten verarbeitet, die vom Dienst zurückgesendet werden. Eine InstanceContext Klasse wird mit einer Instanz der CallbackHandler Klasse erstellt. Dieses Objekt verarbeitet Nachrichten, die vom Dienst an den Client auf der Rückrufschnittstelle gesendet werden.
// Construct InstanceContext to handle messages on callback interface
InstanceContext instanceContext = new InstanceContext(new CallbackHandler());
// Create a client
CalculatorDuplexClient client = new CalculatorDuplexClient(instanceContext);
' Construct InstanceContext to handle messages on callback interface
Dim instanceContext As New InstanceContext(New CallbackHandler())
' Create a client
Dim client As New CalculatorDuplexClient(instanceContext)
Die Konfiguration für den Dienst muss so eingerichtet werden, dass eine Bindung bereitgestellt wird, die sowohl sitzungskommunikation als auch Duplexkommunikation unterstützt. Das wsDualHttpBinding Element unterstützt die Sitzungskommunikation und ermöglicht die Duplexkommunikation, indem zwei HTTP-Verbindungen bereitgestellt werden, eine für jede Richtung.
Auf dem Client müssen Sie eine Adresse konfigurieren, mit der der Server eine Verbindung mit dem Client herstellen kann, wie in der folgenden Beispielkonfiguration gezeigt.
Hinweis
Nichtduplex-Clients, bei denen keine Authentifizierung über eine sichere Konversation möglich ist, lösen in der Regel eine MessageSecurityException aus. Wenn jedoch bei einem Duplexclient, der eine sichere Konversation verwendet, keine Authentifizierung möglich ist, erhält der Client stattdessen eine TimeoutException.
Wenn Sie einen Client/Dienst mit dem WSHttpBinding Element erstellen und den Clientrückrufendpunkt nicht einschließen, wird die folgende Fehlermeldung angezeigt.
HTTP could not register URL
htp://+:80/Temporary_Listen_Addresses/<guid> because TCP port 80 is being used by another application.
Der folgende Beispielcode zeigt, wie die Clientendpunktadresse programmgesteuert angegeben wird.
WSDualHttpBinding binding = new WSDualHttpBinding();
EndpointAddress endptadr = new EndpointAddress("http://localhost:12000/DuplexTestUsingCode/Server");
binding.ClientBaseAddress = new Uri("http://localhost:8000/DuplexTestUsingCode/Client/");
Dim binding As New WSDualHttpBinding()
Dim endptadr As New EndpointAddress("http://localhost:12000/DuplexTestUsingCode/Server")
binding.ClientBaseAddress = New Uri("http://localhost:8000/DuplexTestUsingCode/Client/")
Der folgende Beispielcode zeigt, wie die Clientendpunktadresse in der Konfiguration angegeben wird.
<client>
<endpoint name ="ServerEndpoint"
address="http://localhost:12000/DuplexTestUsingConfig/Server"
bindingConfiguration="WSDualHttpBinding_IDuplexTest"
binding="wsDualHttpBinding"
contract="IDuplexTest" />
</client>
<bindings>
<wsDualHttpBinding>
<binding name="WSDualHttpBinding_IDuplexTest"
clientBaseAddress="http://localhost:8000/myClient/" >
<security mode="None"/>
</binding>
</wsDualHttpBinding>
</bindings>
Warnung
Das Duplexmodell erkennt nicht automatisch, wenn ein Dienst oder Client seinen Kanal schließt. Wenn ein Client also unerwartet beendet wird, wird der Dienst standardmäßig nicht benachrichtigt, oder wenn ein Dienst unerwartet beendet wird, wird der Client nicht benachrichtigt. Wenn Sie einen Dienst verwenden, der getrennt ist, wird die CommunicationException Ausnahme ausgelöst. Clients und Dienste können ihr eigenes Protokoll implementieren, um einander zu benachrichtigen, wenn sie es wünschen. Weitere Informationen zur Fehlerbehandlung finden Sie unter WCF-Fehlerbehandlung.