Step 1:
Start the Visual Studio 2008 and click File->New->Web Site. Select the 'WCF Service' as shown below.
Step 2:
Create interface and decorate with Service and Operation contract.
[ServiceContract()] public interface ISimpleCalculator { [OperationContract] int Add(int num); [OperationContract] int Subtract(int num); [OperationContract] int Multiply(int num); [OperationContract] void EndPersistence(); }
Step 3:
You need to add [Serializable] And [DurableService()] attribute to the
service implementation. Set CanCreateInstance = true property to the
operation in which instance state has to be persisted and set
CompletesInstance = true when state has to be destroyed. In this
implementation, we are going to persist the 'currentValue' variable
value to the database.
using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using System.ServiceModel.Description; [Serializable] [DurableService()] public class SimpleCalculator :ISimpleCalculator { int currentValue = default(int); [DurableOperation(CanCreateInstance = true)] public int Add(int num) { return (currentValue += num); } [DurableOperation()] public int Subtract(int num) { return (currentValue -= num); } [DurableOperation()] public int Multiply(int num) { return (currentValue *= num); } [DurableOperation(CompletesInstance = true)] public void EndPersistence() { }
Step 4:
Before configuring the database information in the durable service, you
need to set up DataStore environment. Microsoft provides inbuilt
sqlPersistance provider. To set up the database environment, run the
these sql query located at following location
'C:\Windows\Microsoft.NET\Framework\v3.5\SQL\EN'
- SqlPersistenceProviderSchema.sql
- SqlPersistenceProviderLogic.sql
Step 5:
In order to support durable service, you need to use Context binding type. <persistenceProvider> tag is used to configure the persistence provider.
<system.serviceModel> <services> <service name="SimpleCalculator" behaviorConfiguration="ServiceBehavior"> <!-- Service Endpoints --> <endpoint address="" binding="wsHttpContextBinding" bindingConfiguration="browConfig" contract="ISimpleCalculator"> <identity> <dns value="localhost"/> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="ServiceBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true"/> <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> <bindings> <wsHttpContextBinding > <binding name="browConfig" > <security mode="None"></security> </binding> </wsHttpContextBinding> </bindings> </system.serviceModel> <connectionStrings> <add name="DurableServiceStore" connectionString="Data Source=saravanakumar;Initial Catalog =DurableServiceStore;Integrated Security=True"/> </connectionStrings>
Step 9:
Create the Helper class called it as Helper.cs. This helper class is
used to Store, Retrieve and set the context at the client side. Context
information will be saved in 'token_context.bin' file. Copy and paste
the below code to your helper file.
Helper.cs
Helper.cs
using System.ServiceModel.Channels; using System.ServiceModel; using System.Net; using System.IO; using System.Runtime.Serialization.Formatters.Binary; public class Helper { static readonly String TokenContextFileName = "token_context.bin"; public static IDictionary<String, String> LoadContext() { IDictionary<String, String> ctx = null; try { using (FileStream fs = new FileStream(TokenContextFileName, FileMode.Open, FileAccess.Read)) { BinaryFormatter bf = new BinaryFormatter(); ctx = bf.Deserialize(fs) as IDictionary<String, String>; fs.Close(); } } catch (Exception ex) { } return ctx; } public static void SaveContext(IClientChannel channel) { IDictionary<String, String> ctx = null; IContextManager cm = channel.GetProperty<IContextManager>(); if (cm != null) { ctx = cm.GetContext() as IDictionary<String, String>; try { using (FileStream fs = new FileStream(TokenContextFileName, FileMode.CreateNew)) { BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(fs, ctx); fs.Close(); } } catch (Exception ex) { } } } public static void DeleteContext() { try { File.Delete(TokenContextFileName); } catch (Exception ex) { } } public static void SetContext(IClientChannel channel, IDictionary<String, String> ctx) { IContextManager cm = channel.GetProperty<IContextManager>(); if (cm != null) { cm.SetContext(ctx); } } }
Step 10:
In the main method, I was creating the proxy for the service and calling
the Add operation. Call to this method will add instance state to the
database. Now I have closed the proxy and creating new proxy instance.
When I call the Subtract and Multiply operation, it will operate on the
previously saved value (instance state).
End of the proxy 1, service instance saved in the database as shown below.
static void Main(string[] args) { //Create the proxy for the service SimpleCalculatorService.SimpleCalculatorClient client = new SimpleCalculatorService.SimpleCalculatorClient "WSHttpContextBinding_ISimpleCalculator"); int currentValue = 0; //Call the Add method from the service currentValue = client.Add(10000); Console.WriteLine("The current value is {0}", currentValue); //Save the Context from the service to the client Helper.SaveContext(client.InnerChannel); //Close the proxy client.Close(); //Create new Instance of the proxy for the service client = new SimpleCalculatorService.SimpleCalculatorClient ("WSHttpContextBinding_ISimpleCalculator"); //Load the context from the client to start from saved state IDictionary<string,string> cntx=Helper.LoadContext(); //Set Context to context manager Helper.SetContext(client.InnerChannel, cntx); //Call the Subtract and Multiply method from service currentValue = client.Subtract(2); Console.WriteLine("The current value is {0}", currentValue); currentValue = client.Multiply(5); Console.WriteLine("The current value is {0}", currentValue); //Delete the context from the client Helper.DeleteContext(); //Remove persistance state from the server client.EndPersistence(); Console.WriteLine("Press <ENTER> to shut down the client."); Console.ReadLine(); client.Close(); }
Serialized XML instance state save in the database is shown below.
Output of the client application.
No comments:
Post a Comment