Monday, April 1, 2013

WCF Durable Services


http://componotech.com/2008/01/wcf-durable-services/
Overview
Durable Services are a new type of service for .NET 3.5 that allow developers to easily manage long running conversations between a service and its clients. The framework provides persistent (durable) state information between calls by serializing state information after each call for each client. That state information can be stored in a database, file system, or any other non-transient store. When each subsequent call is made by the client, the service automatically retrieves the associated state using a token passed in the SOAP header or HTTP cookie. The token is available to the service through the DurableOperationContext.InstanceId.
Durable Services…
· Automatically manage long running conversations. Even if a session is destroyed, the state information is persisted and can be restored at a later time.
· Provide automatic and durable (across machine reboots, session destruction, etc.) state information via pluggable provider. You can configure SqlPersistenceProviderFactory or create a custom child of PersistenceProviderFactory.
· Durable Services use conversation tokens to keep track of client’s state. These tokens are automatically propagated in the SOAP header or http cookie.
· There are new context bindings that support managing the context token between client and service:
o WSHttpContextBinding
o NetTcpContextBinding
o BasicContextBinding
Alternatively you can create a custom binding to which you add a context binding element.
· Durable Services will almost always be used in conjunction with Workflow Services.
Even though all of the durable service classes live in the System.ServiceModel.* namespaces, they exist in the System.WorkflowServices assembly. Now why would Microsoft place the durable service classes in the System.WorkflowServices? I think it’s because durable Services are really the glue that makes WCF and WF such complimentary technologies. WCF abstracts out the protocol and other plumbing specifics that application developers shouldn’t have to deal with. WF provides a new way of mapping business processes and other workflows to often long running activities. When used together, application developers theoretically can focus on writing business specific code in a highly maintainable, easily configurable environment.
Implementation
The implementation of durable services is very similar to implementing reliable sessions. W00t! for a unified programming model! If you have experience with reliable sessions, this should be somewhat reminiscent. We will use the SqlPersistenceProviderFactory that comes with the framework. First, we have to setup the store by running these scripts:
“%windir%\Microsoft.Net\Framework\v3.5\SQL\EN\SqlPersistenceService_Schema.sql”
“%windir%\Microsoft.Net\Framework\v3.5\SQL\EN\SqlPersistenceService_Logic.sql”
Here is what my configuration file looks like. Notice the new wsHttpContextBinding as well as the persistenceProvider section under the behavior configuration. There are several configuration settings that you can change that I won’t go into here. Check it out on MSDN or play around with the Service Configuration Editor tool.
Finally, here and here are the ultra simple service interface and service type implementation. Notice that the InstanceId Guid is available through the DurableOperationContext.InstanceId property. When a client passes the context token to the service, the framework automatically uses the token to rehydrate that client’s state.
As always, if you have any questions please feel free to email me.
More about Durable Services:



Tutorial: Create a Durable Service
.NET Framework 3.5
3 out of 3 rated this helpful - Rate this topic
Durable services are Windows Communication Foundation (WCF) services that use context bindings, attributes, and new configuration elements to persist service state information to a store, such as a SQL database, which means that durable services have the capability to restore their own state when they are recycled. Durable services are useful when implementing long-running stateful conversations.
In this tutorial, you will create a durable service that persists its state information to a SQL database.
In This Section
Reference


Task 1: Define and Implement the Durable Service Contract
.NET Framework 3.5
0 out of 2 rated this helpful - Rate this topic
In this task, you will define and implement the service contract for your durable service.
Defining the contract
1.      Open Visual Studio 2008, click File, and select New and then Project.
2.      In the New Project dialog box, under WCF, select the WCF Service Library template.
3.      Name your project SimpleDurableService and click OK.
Visual Studio 2008 generates the following files for your WCF service: an App.config file to store configuration settings, a source file that contains a contract definition, and a source file that contains the service class that implements the contract definition.
The template creates a service with two operations and a data contract for a custom type. In this tutorial, you will define new operations for your durable service.
4.      Open IService1.cs (or IService1.vb if you created a Visual Basic solution) and replace the existing interface definition with the following code and remove the existing DataContractAttribute definition.
C#
[ServiceContract]
public interface IService1
{
    [OperationContract]
    int Add(int n1);

    [OperationContract]
    int Subtract(int n1);

    [OperationContract]
    int Multiply(int n1);

    [OperationContract]
    void EndPersistence();
}

1.      Open Service1.cs (or Service1.vb if you created a Visual Basic solution).
2.      Implement the updated IService1 interface in your Service1 class definition.

Visual Studio automatically creates default implementations for your interface methods, which you will modify in the next step.
3.      Modify the existing class definition to perform the appropriate logic as shown in the following code:
C#
public class Service1 : IService1
{
    int currentValue = default(int);

    #region IService1 Members

    public int Add(int n1)
    {
        return (currentValue += n1);
    }

    public int Subtract(int n1)
    {
        return (currentValue -= n1);
    }

    public int Multiply(int n1)
    {
        return (currentValue *= n1);
    }

    public void EndPersistence()
    {
    }
    #endregion
}

At this point, the WCF service you created is exactly the same as any WCF service you created in .NET Framework 3.0. The next task will show you how to take this service and persist its current state to a persistence store so that in the event your service is disconnected from the client, you can communicate with the client again at a later time from the last successful operation that was invoked.


Task 2: Enable Persistence for the Durable Service
.NET Framework 3.5
This topic has not yet been rated - Rate this topic
In this task, you will decorate the service you created in Task 1 with attributes that enable you to persist the state of your service after every successful operation invocation.
To decorate the service with durable service attributes
1.      Open Service1.cs (or Service1.vb if you created a Visual Basic solution).
2.      In the Solution Explorer pane, under the SimpleDurableService project node, right-click the References subfolder and select Add Reference.
3.      In the Add Reference dialog box, under the .NET tab, select System.WorkflowServices and click OK.
4.      Add the following using statement in your C# source file:
C#
using System.ServiceModel.Description;

If you created a Visual Basic solution, right-click the SimpleDurableService project node and select Properties. Select the References tab, and under Imported Namespaces, check System.ServiceModel.Description.
1.      To persist your service, you must decorate the Service1 class with the DurableServiceAttribute and SerializableAttribute attributes as shown in the following example.

C#
[Serializable]
[DurableService]
public class Service1 : IService1
{
    // The class definition was omitted for clarity.
}

1.      The DurableServiceAttribute attribute specifies that state information for your WCF service can be persisted to a persistence store, such as a database or file. Also, the service type must be serializable so that it can be transmitted to the persistence store.
2.      Decorate the service operations with the DurableOperationAttribute attribute as shown in the following example. This attribute specifies that the service instance state will be saved after the operation has completed.

C#
[DurableOperation(CanCreateInstance = true)]
public int Add(int n1)
{
    return (currentValue += n1);
}

[DurableOperation]
public int Subtract(int n1)
{
    return (currentValue -= n1);
}

[DurableOperation]
public int Multiply(int n1)
{
    return (currentValue *= n1);
}

[DurableOperation(CompletesInstance = true)]
public void EndPersistence()
{
}

The CanCreateInstance and CompletesInstance properties specify that the durable service instance will either be created or completed after the decorated operation has successfully completed. In this tutorial, several operations have the first and last operations controlling the behavior of the service instance.
Operations that are decorated with the DurableOperationAttribute attribute set to default values can only persist state information to an existing service instance entry in the persistence store. However, if you create a service contract where System.ServiceModel.SessionMode.NotAllowed is set to true, every DurableOperationAttribute attribute must have the CanCreateInstance property set to true.
Now that your service is decorated with the proper attributes, you must set up your configuration file and reference the persistence store you want to use.
To configure your durable service
1.      Open App.config.
2.      Modify the endpoint configuration settings to reference a context binding, such as WSHttpContextBinding.
<endpoint address ="" binding="wsHttpContextBinding" contract="SimpleDurableService.IService1" />
Context bindings must be used because a DurableOperationContext is used by the client to identify a specific service instance. After invoking a request/response operation and receiving a response from the service, the client will use the InstanceId value on each subsequent operation invocation so that the client associates itself with the correct service instance. If this tracking mechanism was not used, then when a service instance is either shut down or disconnected from the client, the client would not be able to reestablish a connection to a specific service instance.
3.      Add the following child node to your behavior node.
<behaviors>
      <serviceBehaviors>
        <behavior name="SimpleDurableService.Service1Behavior">
          <!-- To avoid disclosing metadata information,
          set the following value to false and remove the preceding metadata endpoint before deployment. -->
          <serviceMetadata httpGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes,
          set the following value to true. Set the value to false before deployment
          to avoid disclosing exception information. -->
          <serviceDebug includeExceptionDetailInFaults="False" />
          <persistenceProvider type="System.ServiceModel.Persistence.SqlPersistenceProviderFactory, System.WorkflowServices, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                               connectionStringName="DurableServiceStore"
                               persistenceOperationTimeout = "00:00:10"
                               lockTimeout="00:01:00"
                               serializeAsText="true"/>

        </behavior>
      </serviceBehaviors>
    </behaviors>
The PersistenceProviderElement defines the type of PersistenceProvider that your service will use. In this tutorial, the SqlPersistenceProviderFactory is used to create a new instance of the PersistenceProvider type that connects to a SQL database. Whenever the Add operation is invoked and successfully completes, a new service instance will be created and its state information will be stored in the SQL database.
4.      Add the connection string for the SQL database that your service instance will use for persistence.
  </system.serviceModel>
  <connectionStrings>
    <add name="DurableServiceStore" connectionString="Data Source=localhost\SQLEXPRESS;Initial Catalog=NetFx35Samples_DurableServiceStore;Integrated Security=SSPI"/>
  </connectionStrings>
</configuration>
Bb675272.note(en-us,VS.90).gifNote:
This tutorial uses the same database that is used for the Durable Workflow Services Sample; therefore, the connection string is the same. To allow access to the durable store, run the Createstores.cmd script from One-Time Setup Procedure for the Windows Communication Foundation Samples.



Task 3: Create a Durable Service Client
.NET Framework 3.5
1 out of 1 rated this helpful - Rate this topic
In this task, you will create a simple client to invoke operations on your durable service. The testing tool WcfTestClient.exe is used by the WCF Service Library template.
Creating the client
1.      In the SimpleDurableService solution, right-click the solution node in the Solution Explorer pane.
2.      Navigate to Add and select New Project.
3.      In the New Project dialog box, under Windows, select Console Application.
4.      Name your project DurableServiceTestClient and click OK.
5.      Right-click the DurableServiceTestClient project node and select Add Reference.
6.      In the Add Reference dialog box, in the .NET tab, select the System.ServiceModel assembly and click OK.
7.      Add the following using statement to your C# source file:
VB
Imports System.ServiceModel

If you created a Visual Basic solution, right-click the DurableServiceTestClient project node and select Properties. Select the References tab, and under Imported Namespaces, check System.ServiceModel.
1.      Use SvcUtil.exe to generate the proxy code and configuration file for your durable service.

Using SvcUtil.exe

To use SvcUtil.exe, see ServiceModel Metadata Utility Tool.

After you have generated your proxy code and configuration files, add those files to your DurableServiceTestClient project by doing the following:
1.      Navigate to the Solution Explorer pane.
2.      Right-click the DurableServiceTestClient project node.
3.      Highlight Add and select Existing Item.
4.      Navigate to the folder where SvcUtil.exe generated the configuration and proxy code files.
5.      Select the files and click OK.
6.      Rename your configuration file to App.config if it is not named that already.
2.      Add the following code to your Main method implementation:

C#
static void Main(string[] args)
{
    Service1Client client = new Service1Client("WSHttpContextBinding_IService1");
    client.Open();
    int currentValue = default(int);
    currentValue = client.Add(3);
    Console.WriteLine("The current value is {0}", currentValue);
    currentValue = client.Subtract(4);
    Console.WriteLine("The current value is {0}", currentValue);
    currentValue = client.Multiply(5);
    Console.WriteLine("The current value is {0}", currentValue);
    client.EndPersistence();
    Console.WriteLine("Press <ENTER> to shut down the client.");
    Console.ReadLine();
    client.Close();
}

Durable service clients are created in the same way as regular WCF service clients. A new instance of the client is created based off of the proxy code of the service. Next, a call to Open is made followed by the invocation of the service operations. Finally, a call to Close is made to shut down the client.
1.      To use the client with your durable service in the SimpleDurableService solution, you must delete a command-line argument from the SimpleDurableService project properties. To do so, perform the following steps:
1.      Right-click the SimpleDurableService project node and select Properties.
2.      Select the Debug tab, and in the detail pane under Start Options, remove /client:"WfcTestClient.exe" from the text box.
2.      Right-click the SimpleDurableService solution node and select Properties.
3.      In the Property Pages dialog box, select Multiple startup projects.
4.      If SimpleDurableService is not listed as the top item in the list, use the arrows on the side of the list box to make it the top item. This is needed so that your service starts running before your client application tries to invoke any operations on the service.
5.      For each project in the list, change the action from None to Start.
6.      Click Apply and then OK.
7.      Build both the service and client projects. You can host your durable service in IIS, a Windows application, or any other host process, but for the purposes of this tutorial, you will host it in WfcSvcHost.exe. WcfSvcHost.exe is a developer tool that hosts services for testing purposes.

You should observe the following output from the client's command-line interface:
The current value is 3
The current value is -1
The current value is -5
Press <ENTER> to shut down the client.
One way to observe that persistence is occurring after every operation (with the exception of EndPersistence), is to install Microsoft SQL Server Management Studio Express from http://www.microsoft.com/downloads and set debug points throughout your client app. After you hit those points, observe the InstanceData table in the NetFx35Samples_DurableServiceStore database. You should see a new entry being added to the table, then updated after every operation until the EndPersistence call completes, at which time the table entry will be removed.

Another way to see the value of the durable service is to make the first operation invocations to the service from your client and in Visual Studio put a breakpoint on the operation invocation. Before executing the third operation invocation, shut the service down and restart the service. Now make the operation invocation. The state of the service is now restored from the persistence database and you will be able to see that the service gives you back the reply desired for the current value.


No comments:

Post a Comment

 using Microsoft.AspNetCore.Mvc; using System.Xml.Linq; using System.Xml.XPath; //<table class="common-table medium js-table js-stre...