Megosztás a következőn keresztül:


Kétoldalas szolgáltatások

A kétoldalas szolgáltatási szerződés olyan üzenetcsere-minta, amelyben mindkét végpont egymástól függetlenül küldhet üzeneteket a másiknak. A kétoldalas szolgáltatások ezért vissza tudnak küldeni üzeneteket az ügyfélvégpontra, így eseményszerű működést biztosítanak. Kétoldalas kommunikáció akkor fordul elő, ha egy ügyfél csatlakozik egy szolgáltatáshoz, és olyan csatornát biztosít a szolgáltatásnak, amelyen a szolgáltatás üzeneteket küldhet vissza az ügyfélnek. Vegye figyelembe, hogy a kétoldalas szolgáltatások eseményszerű viselkedése csak egy munkameneten belül működik.

Kétoldalas szerződés létrehozásához létre kell hoznia egy pár interfészt. Az első a szolgáltatási szerződés felülete, amely leírja az ügyfél által meghívható műveleteket. A szolgáltatási szerződésnek meg kell adnia egy visszahívási szerződést a ServiceContractAttribute.CallbackContract tulajdonságban. A visszahívási szerződés az a felület, amely meghatározza azokat a műveleteket, amelyeket a szolgáltatás meghívhat az ügyfélvégponton. A kétoldalas szerződések nem igényelnek munkamenetet, bár a rendszer által biztosított kétoldalas kötések használják őket.

Az alábbi példa kétoldalas szerződésre mutat be példát.

[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

Az CalculatorService osztály implementálja az elsődleges ICalculatorDuplex felületet. A szolgáltatás a PerSession példánymódot használja az egyes munkamenetek eredményének fenntartásához. A névvel ellátott Callback magántulajdonság hozzáfér a visszahívási csatornához az ügyfélhez. A szolgáltatás a visszahívás használatával küldi vissza az üzeneteket az ügyfélnek a visszahívási felületen keresztül, ahogyan az az alábbi mintakódban látható.


[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

Az ügyfélnek meg kell adnia egy osztályt, amely megvalósítja a kétoldalas szerződés visszahívási felületét a szolgáltatástól érkező üzenetek fogadásához. Az alábbi mintakód egy olyan osztályt CallbackHandler mutat be, amely implementálja az interfészt ICalculatorDuplexCallback .

public class CallbackHandler : ICalculatorDuplexCallback
{
    public void Equals(double result)
    {
        Console.WriteLine("Equals({0})", result);
    }

    public void Equation(string eqn)
    {
        Console.WriteLine("Equation({0})", 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

A kétoldalas szerződéshez létrehozott WCF-ügyfélnek az építéskor meg kell adni egy InstanceContext osztályt. Ez InstanceContext az osztály egy olyan objektum webhelye, amely megvalósítja a visszahívási felületet, és kezeli a szolgáltatásból visszaküldött üzeneteket. Az InstanceContext osztály az osztály egy példányával CallbackHandler jön létre. Ez az objektum kezeli a szolgáltatásból az ügyfélnek a visszahívási felületen küldött üzeneteket.

// 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)

A szolgáltatás konfigurációját úgy kell beállítani, hogy olyan kötést biztosítson, amely támogatja a munkamenet-kommunikációt és a kétoldalas kommunikációt is. Az wsDualHttpBinding elem támogatja a munkamenet-kommunikációt, és lehetővé teszi a kétirányú kommunikációt kettős HTTP-kapcsolatok biztosításával, amelyek mindegyik irányban egy-egyhez csatlakoznak.

Az ügyfélen konfigurálnia kell egy címet, amelyet a kiszolgáló az ügyfélhez való csatlakozáshoz használhat az alábbi mintakonfigurációban látható módon.

Feljegyzés

Azok a nem kétoldalas ügyfelek, amelyek nem hitelesíthetők biztonságos beszélgetéssel, általában egy MessageSecurityException. Ha azonban egy biztonságos beszélgetést használó kétoldalas ügyfél hitelesítése sikertelen, az ügyfél ehelyett kap egy ilyen ügyfelet TimeoutException .

Ha az WSHttpBinding elemet használva hoz létre egy ügyfelet/szolgáltatást, és nem tartalmazza az ügyfélvisszahívási végpontot, a következő hibaüzenet jelenik meg.

HTTP could not register URL
htp://+:80/Temporary_Listen_Addresses/<guid> because TCP port 80 is being used by another application.

Az alábbi mintakód bemutatja, hogyan adhatja meg az ügyfélvégpont címét programozott módon.

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/")

Az alábbi mintakód bemutatja, hogyan adhatja meg az ügyfélvégpont címét a konfigurációban.

<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>

Figyelmeztetés

A kétoldalas modell nem észleli automatikusan, ha egy szolgáltatás vagy ügyfél bezárja a csatornáját. Így ha egy ügyfél váratlanul leáll, alapértelmezés szerint a szolgáltatás nem fog értesítést kapni, vagy ha egy szolgáltatás váratlanul leáll, az ügyfél nem fog értesítést kapni. Ha leválasztott szolgáltatást használ, a CommunicationException rendszer kivételt emel ki. Az ügyfelek és a szolgáltatások saját protokollt alkalmazhatnak, hogy értesítsék egymást, ha úgy döntenek. A hibakezeléssel kapcsolatos további információkért lásd: WCF hibakezelés.

Lásd még