CSharpFeeds - All your C# feeds in one place.

Sponsors

Friday, May 11, 2007

Transaction Flow in Windows Communication Foundation

by Keyvan Nayyeri via Keyvan Nayyeri on 5/11/2007 3:57:08 PM

I'm pretty sure that everybody who reads my blog, has good information about transactions and their definitions but in one sentence transactions are a group of operations that act as an atomic unit.

WCF supports transaction flows out of the box.  But what does transaction flow mean?  Transaction flow means that if a client creates a proxy to one or more services and call their operations in a sequence and one of these operations fails then client completely fails.

There is a requirement to enable transaction flows for WCF: two-way communication between clients and services.

Apparently you know how to create a transaction using TransactionScope block and use its Complete() method to commit the transactions.

To enable transaction flow for your WCF applications you must enable it for service and client binding configurations explicitly (as you will see in a moment).  After this, you can use transaction flow in your applications without any problem.

I write a sample application (service and client) to show all details to enable transaction flow in WCF applications step by step.  If you need more information about writing WCF services and clients and hosting concepts, read my article about developing WCF applications on ASP Alliance.

Service

First of all I create a service project and a service contract for it (unlike VS 2005, in Orcas default project template for WCF services generates separate files for contract and service implementation).

using System;

using System.Runtime.Serialization;

using System.ServiceModel;

 

namespace MyService

{

    [ServiceContract]

    public interface IMyService

    {

        [OperationContract]

        int Method1(int x, int y);

 

        [OperationContract]

        int Method2(int x, int y);

    }

}

This service requires a service implementation as well.

using System;

 

namespace MyService

{

    public class TempService : IMyService

    {

        #region IMyService Members

 

        public int Method1(int x, int y)

        {

            return ((x + y) * 2);

        }

 

        public int Method2(int x, int y)

        {

            return ((x + y) * 4);

        }

 

        #endregion

    }

}

After compiling this service into a DLL file I use it to host my service on IIS.  This needs a .svc file and a Web.Config file.  In Web.Config I use wsHttpBinding as my binding but set its transactionFlow attribute to true to enable transaction flow for my service.

<?xml version="1.0"?>

<configuration>

  <system.serviceModel>

    <services>

      <service name="MyService.TempService"

              behaviorConfiguration="metadataSupport">

        <endpoint contract="MyService.IMyService"

                  binding="wsHttpBinding"

                  bindingConfiguration="MyWSBinding"/>

        <endpoint address="mex"

          binding="mexHttpBinding"

          contract="IMetadataExchange"/>

      </service>

    </services>

 

    <bindings>

      <wsHttpBinding>

        <binding name="MyWSBinding" transactionFlow="true"/>

      </wsHttpBinding>

    </bindings>

 

    <behaviors>

      <serviceBehaviors>

        <behavior name="metadataSupport">

          <serviceMetadata />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

Client

After creating my service and hosting it on IIS, I can generate my proxy class and client configuration file using SvcUtil.exe from command line.  Generated configuration file doesn't have transaction flow enabled for client by default so I edit it and set transactionFlow attribute of <binding /> element to true.

<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <system.serviceModel>

    <bindings>

      <wsHttpBinding>

        <binding name="WSHttpBinding_IMyService" closeTimeout="00:01:00"

            openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"

            bypassProxyOnLocal="false" transactionFlow="true" hostNameComparisonMode="StrongWildcard"

            maxBufferPoolSize="524288" maxReceivedMessageSize="65536"

            messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"

            allowCookies="false">

          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"

              maxBytesPerRead="4096" maxNameTableCharCount="16384" />

          <reliableSession ordered="true" inactivityTimeout="00:10:00"

              enabled="false" />

          <security mode="Message">

            <transport clientCredentialType="Windows" proxyCredentialType="None"

                realm="" />

            <message clientCredentialType="Windows" negotiateServiceCredential="true"

                algorithmSuite="Default" establishSecurityContext="true" />

          </security>

        </binding>

      </wsHttpBinding>

    </bindings>

    <client>

      <endpoint address="http://keyvan-pc/MyService/service.svc" binding="wsHttpBinding"

          bindingConfiguration="WSHttpBinding_IMyService" contract="IMyService"

          name="WSHttpBinding_IMyService">

        <identity>

          <servicePrincipalName value="host/Keyvan-PC" />

        </identity>

      </endpoint>

    </client>

  </system.serviceModel>

</configuration>

And last step is to write my client code (ignore the reference to System.Linq.  It's because I wrote this application with .NET 3.5 and that reference is generated automatically).

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Transactions;

 

namespace MyClient

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.Title = "Transaction Flow in WCF";

 

            Console.WriteLine("Enter x:");

            int x = Convert.ToInt32(Console.ReadLine());

            Console.WriteLine("Enter y:");

            int y = Convert.ToInt32(Console.ReadLine());

 

            using (MyServiceClient proxy = new MyServiceClient())

            {

                using (TransactionScope scope =

                    new TransactionScope(TransactionScopeOption.RequiresNew))

                {

                    Console.WriteLine(string.Format("({0} + {1}) * 2 = {2}",

                        x, y, proxy.Method1(x, y).ToString()));

                    Console.WriteLine(string.Format("({0} + {1}) * 4 = {2}",

                        x, y, proxy.Method2(x, y)));

 

                    scope.Complete();

                }

            }

            Console.ReadLine();

        }

    }

}

As you see, I created a proxy and put a TransactionScope block within it.  At the end of block, I used Complete() method to commit transactions.

Output

Now playing: Eminem - Mockingbird

email it!bookmark it!digg it!

Original Post: Transaction Flow in Windows Communication Foundation

Subscribe

New Feed

Product Spotlight

Recently Updated Sources

Legal Note

The content of the postings is owned by the respective author. CSharpFeeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on CSharpFeeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.

Advertise with us