Delen via


Duurzame duplex correlatie

Duurzame duplex-correlatie, ook wel callback-correlatie genoemd, is handig wanneer een werkstroomservice een callback naar de eerste beller moet verzenden. In tegenstelling tot WCF duplex kan de callback op elk gewenst moment in de toekomst plaatsvinden en is deze niet gekoppeld aan hetzelfde kanaal of de levensduur van het kanaal. De enige vereiste is dat de beller een actief eindpunt heeft dat luistert naar het callback-bericht. Hierdoor kunnen twee werkstroomservices communiceren in een langlopend gesprek. Dit artikel bevat een overzicht van duurzame duplex correlatie.

Duurzame duplex-correlatie gebruiken

Als u duurzame dubbelzijdige correlatie wilt gebruiken, moeten de twee services een binding met context gebruiken die ondersteuning biedt voor tweerichtingsbewerkingen, zoals NetTcpContextBinding of WSHttpContextBinding. De aanroepende service registreert een ClientCallbackAddress met de gewenste binding op de client Endpoint. De ontvangende service ontvangt deze gegevens in de eerste aanroep en gebruikt deze vervolgens zelfstandig Endpoint in de Send activiteit waarmee de aanroep naar de aanroepservice wordt teruggezet. In dit voorbeeld communiceren twee services met elkaar. De eerste service roept een methode aan voor de tweede service en wacht vervolgens op een antwoord. De tweede service kent de naam van de callback-methode, maar het eindpunt van de service die deze methode implementeert, is niet bekend tijdens het ontwerp.

Notitie

Duurzame duplex kan alleen worden gebruikt wanneer het AddressingVersion eindpunt is geconfigureerd met WSAddressing10. Als dit niet het probleem is, wordt er een InvalidOperationException uitzondering gegenereerd met het volgende bericht: 'Het bericht bevat een callback-contextheader met een eindpuntverwijzing voor AddressingVersion. Callback-context kan alleen worden verzonden wanneer de AddressingVersion is geconfigureerd met 'WSAddressing10'.

In het volgende voorbeeld wordt een werkstroomservice gehost waarmee een callback Endpoint wordt gemaakt met behulp van WSHttpContextBinding.

// Host WF Service 1.
string baseAddress1 = "http://localhost:8080/Service1";
WorkflowServiceHost host1 = new WorkflowServiceHost(GetWF1(), new Uri(baseAddress1));

// Add the callback endpoint.
WSHttpContextBinding Binding1 = new WSHttpContextBinding();
host1.AddServiceEndpoint("ICallbackItemsReady", Binding1, "ItemsReady");

// Add the service endpoint.
host1.AddServiceEndpoint("IService1", Binding1, baseAddress1);

// Open the first workflow service.
host1.Open();
Console.WriteLine("Service1 waiting at: {0}", baseAddress1);

De werkstroom die deze werkstroomservice implementeert, initialiseert de callback-correlatie met de Send activiteit en verwijst naar dit callback-eindpunt van de Receive activiteit die overeenkomt met de Send. Het volgende voorbeeld vertegenwoordigt de werkstroom die wordt geretourneerd door de GetWF1 methode.

Variable<CorrelationHandle> CallbackHandle = new Variable<CorrelationHandle>();

Receive StartOrder = new Receive
{
    CanCreateInstance = true,
    ServiceContractName = "IService1",
    OperationName = "StartOrder"
};

Send GetItems = new Send
{
    CorrelationInitializers =
    {
        new CallbackCorrelationInitializer
        {
            CorrelationHandle = CallbackHandle
        }
    },
    ServiceContractName = "IService2",
    OperationName = "StartItems",
    Endpoint = new Endpoint
    {
        AddressUri = new Uri("http://localhost:8081/Service2"),
        Binding = new WSHttpContextBinding
        {
            ClientCallbackAddress = new Uri("http://localhost:8080/Service1/ItemsReady")
        }
    }
};

Receive ItemsReady = new Receive
{
    ServiceContractName = "ICallbackItemsReady",
    OperationName = "ItemsReady",
    CorrelatesWith = CallbackHandle,
};

Activity wf = new Sequence
{
    Variables =
    {
        CallbackHandle
    },
    Activities =
    {
        StartOrder,
        new WriteLine
        {
            Text = "WF1 - Started"
        },
        GetItems,
        new WriteLine
        {
            Text = "WF1 - Request Submitted"
        },
        ItemsReady,
        new WriteLine
        {
            Text = "WF1 - Items Received"
        }
     }
};

De tweede werkstroomservice wordt gehost met behulp van een door het systeem geleverde, contextgebaseerde binding.

// Host WF Service 2.
string baseAddress2 = "http://localhost:8081/Service2";
WorkflowServiceHost host2 = new WorkflowServiceHost(GetWF2(), new Uri(baseAddress2));

// Add the service endpoint.
WSHttpContextBinding Binding2 = new WSHttpContextBinding();
host2.AddServiceEndpoint("IService2", Binding2, baseAddress2);

// Open the second workflow service.
host2.Open();
Console.WriteLine("Service2 waiting at: {0}", baseAddress2);

De werkstroom die deze werkstroomservice implementeert, begint met een Receive activiteit. Deze ontvangstactiviteit initialiseert de callback-correlatie voor deze service, vertraagt gedurende een bepaalde periode om langlopend werk te simuleren en roept vervolgens terug naar de eerste service met behulp van de callback-context die is doorgegeven in de eerste aanroep naar de service. Het volgende voorbeeld vertegenwoordigt de werkstroom die wordt geretourneerd door een aanroep naar GetWF2. De Send activiteit heeft een tijdelijke aanduiding voor het adres van http://www.contoso.com; het werkelijke adres dat tijdens de runtime wordt gebruikt, is het opgegeven callback-adres.

Variable<CorrelationHandle> ItemsCallbackHandle = new Variable<CorrelationHandle>();

Receive StartItems = new Receive
{
    CorrelationInitializers =
    {
        new CallbackCorrelationInitializer
        {
            CorrelationHandle = ItemsCallbackHandle
        }
    },
    CanCreateInstance = true,
    ServiceContractName = "IService2",
    OperationName = "StartItems"
};

Send ItemsReady = new Send
{
    CorrelatesWith = ItemsCallbackHandle,
    Endpoint = new Endpoint
    {
        // The callback address on the binding is used
        // instead of this placeholder address.
        AddressUri = new Uri("http://www.contoso.com"),

        Binding = new WSHttpContextBinding()
    },
    OperationName = "ItemsReady",
    ServiceContractName = "ICallbackItemsReady"
};

Activity wf = new Sequence
{
    Variables =
    {
        ItemsCallbackHandle
    },
    Activities =
    {
        StartItems,
        new WriteLine
        {
            Text = "WF2 - Request Received"
        },
        new Delay
        {
            Duration = TimeSpan.FromMinutes(90)
        },
        new WriteLine
        {
            Text = "WF2 - Sending items"
        },
        ItemsReady,
        new WriteLine
        {
            Text = "WF2 - Items sent"
        }
     }
};

Wanneer de StartOrder methode wordt aangeroepen in de eerste werkstroom, wordt de volgende uitvoer weergegeven, waarin de uitvoeringsstroom via de twee werkstromen wordt weergegeven.

Service1 waiting at: http://localhost:8080/Service1
Service2 waiting at: http://localhost:8081/Service2
Press enter to exit.
WF1 - Started
WF2 - Request Received
WF1 - Request Submitted
WF2 - Sending items
WF2 - Items sent
WF1 - Items Received

In dit voorbeeld beheren beide werkstromen expliciet correlatie met behulp van een CallbackCorrelationInitializer. Omdat er slechts één correlatie was in deze voorbeeldwerkstromen, was het standaardbeheer CorrelationHandle voldoende.