none
Transaction not flowing from client through to WCF service (timing out) RRS feed

  • Question

  • I have been struggling to add transaction control (using System.Transactions.TransactionScope) to an existing, working, WCF service. After setting up MS DTC and opening ports in the firewall, I finally got to a point where the WCF service worked again, but I had intentionally not committed/completed the transaction, and yet my database changes were not being rolled back as expected.

    To investigate further, I set <TransactionFlow(TransactionFlowOption.Mandatory)> on the method calls. This resulted in errors on the client of "<Message>The requested service, 'https://(...omitted...)/LegacyUnitAppService/BeginTest.svc/wsHTTPSEndPoint' could not be activated. See the server's diagnostic trace logs for more information.</Message>"

    Next, I added transactionFlow="true" to wsHttpBinding in the web.config, and added binding.TransactionFlow = True to the service code, and got "The service operation requires a transaction to be flowed.

    Finally, I updated the Service reference in the service code and I now get "The request channel timed out while waiting for a reply after 00:01:00. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout."

    I know from my previous working WCF service that it's not timing out due to the database calls. And, I do not believe it is even making it into the service code, because none of my logging (which is working fine) is occurring on the service side. The client is definitely waiting the minute and timing out for each call. I believe the timeout is simply an indication of some further misconfiguration on my part, but I can't see anything obvious I'm doing wrong.

    We are using Visual Studio 2010 Ultimate (VB.NET), SQL Server 2008 R2, and IIS 7.

    Client code transaction wrapper:

    Dim topt As New System.Transactions.TransactionOptions
    topt.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted
    topt.Timeout = System.Transactions.TransactionManager.MaximumTimeout
    Using ts As New System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, topt)
        (...function call here, but not the WCF call...) 
        'ts.Complete()
    End Using

    The actual WCF call from the client side (different class library, but running in the same thread as the code above).

    Private MyBeginTestService As BeginTestService.BeginTestClient = Nothing
    
    (...)
    
    Dim binding As New System.ServiceModel.WSHttpBinding(System.ServiceModel.SecurityMode.Transport)
    binding.MaxReceivedMessageSize = Integer.MaxValue
    binding.TransactionFlow = True
    
    Dim AppServerURL As String = Sti.Utilities.Config.GetInstance.ReadText("AppServer", "BeginTestURL", "https://(omitted)/LegacyUnitAppService/BeginTest.svc/wsHTTPSEndPoint")
    Dim Endpointaddress As New System.ServiceModel.EndpointAddress(AppServerURL)
    MyBeginTestService = New BeginTestService.BeginTestClient(binding, Endpointaddress)
    
    (...)
    
    MyBeginTestService.LogRequest(...args omitted...)

    app.config:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <system.diagnostics>
            <sources>
                <!-- This section defines the logging configuration for My.Application.Log -->
                <source name="DefaultSource" switchName="DefaultSwitch">
                    <listeners>
                        <add name="FileLog"/>
                        <!-- Uncomment the below section to write to the Application Event Log -->
                        <!--<add name="EventLog"/>-->
                    </listeners>
                </source>
            </sources>
            <switches>
                <add name="DefaultSwitch" value="Information" />
            </switches>
            <sharedListeners>
                <add name="FileLog"
                     type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"
                     initializeData="FileLogWriter"/>
                <!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
                <!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
            </sharedListeners>
        </system.diagnostics>
        <system.serviceModel>
            <bindings>
                <wsHttpBinding>
                    <binding name="wsHttpSsl" 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="Transport">
                            <transport clientCredentialType="None" proxyCredentialType="None"
                                realm="" />
                            <message clientCredentialType="Windows" negotiateServiceCredential="true" />
                        </security>
                    </binding>
                    (...other bindings omitted...)
                </wsHttpBinding>
            </bindings>
            <client>
                <endpoint address="https://(...omitted...)/LegacyUnitAppService/BeginTest.svc/wsHTTPSEndPoint"
                    binding="wsHttpBinding" bindingConfiguration="wsHttpSsl" contract="BeginTestService.IBeginTest"
                    name="wsHttpSsl" />
                (...other endpoints omitted...)
            </client>
        </system.serviceModel>
    </configuration>
    


    Service side web.config:

    <?xml version="1.0"?>
    <configuration>
      <system.web>
        <compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
        <customErrors mode="Off"/>
      </system.web>
      <system.serviceModel>
        <bindings>
          <wsHttpBinding>
            <binding name="wsHttpsBindingConfig" closeTimeout="00:01:00"
              openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
              allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
              maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
              messageEncoding="Text" textEncoding="utf-8"
              useDefaultWebProxy="true" transactionFlow="true">
              <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                maxBytesPerRead="4096" maxNameTableCharCount="16384" />
              <security mode="Transport">
                <transport clientCredentialType="None" />
              </security>
            </binding>
          </wsHttpBinding>
        </bindings>
        <services>
          <service name="Sti.Vid.LegacyUnitAppService.BeginTest">
            <endpoint address="/wsHTTPSEndPoint" binding="wsHttpBinding"
              bindingConfiguration="wsHttpsBindingConfig" name="wsHttpSsl"
              contract="Sti.Vid.LegacyUnitAppService.IBeginTest" />
            <endpoint address="mex" binding="wsHttpBinding" bindingConfiguration="wsHttpsBindingConfig" name="mex" contract="IMetadataExchange" />
          </service>
          (...other services ommitted but they are all extremely similar...)
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoints above before deployment -->
              <serviceMetadata httpsGetEnabled="true"/>
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
      </system.webServer>
    </configuration>

    Interface:

    <ServiceContract()>
    Public Interface IBeginTest
        <OperationContract()>
        <TransactionFlow(TransactionFlowOption.Mandatory)>
        Sub LogRequest(...params omitted...)
    
        (...other methods omitted...)
    End Interface

    BeginTest.svc.vb file:

    Public Class BeginTest
        Implements IBeginTest
    
        (...irrelevant code removed...)
    
        <OperationBehavior(TransactionScopeRequired:=True)>
        Public Sub LogRequest(...params omitted...) Implements IBeginTest.LogRequest
            (...database code omitted...)
        End Sub
    
        (...implementation of other methods omitted...)
    End Class
    Thanks!

    • Edited by jeffryj Wednesday, June 19, 2013 3:51 PM provide app.config
    Wednesday, June 19, 2013 12:14 AM

All replies