locked
Error when uploading large changes in n-tier setup RRS feed

  • Question

  • I am desperate.  I have been struggling with a error with the sync framework in an n-tier setup using WCF web services.  Basically, whenever I try to upload a large batch of changes (gets batched to 5 files) the sync fails with the following error in the WCF trace:

    There was no channel that could accept the message with action 'http://<ComputerName>/IRelationalSyncContract/EndSession'.

    I am using the webappsharing demo code as my starting point.  Any ideas what might be wrong?
    Monday, March 15, 2010 8:57 PM

Answers

  • AHH HELLLL YEAH!  I got it!!!!! 

    Turns out it was all related to the location of the BatchingDirectory.  I had it wired to use a folder called Batching under the root of the asp.net application directory.  Appearently, when you do this, and GetChanges does NOT have any results to batch, IIS closes the channel for you after the call to GetChanges.  I changed my batching directory to be somewhere other than under the web service application and its all fixed!  Only took 4 days to figure that out.  Second longest time I have ever spent to resolve one bug.  All works like a charm.  We are ready to roll into QA!

    Thanks again Steve for helping out!  If you can, send me an email at stewart.armbrecht@protiviti.com.  I'd like to give you something for all your effort.
    Wednesday, March 17, 2010 6:50 PM

All replies

  • I am also seeing a lot of these type of errors in the WCF trace:

    The communication object, System.ServiceModel.Channels.ReplyChannel, cannot be used for communication because it has been Aborted.
    Monday, March 15, 2010 10:17 PM
  • Does anybody have an end to end example of using a web tier that isn't as convoluted as the WebSharingApp demo that tries to act as multiple clients in one app?
    Monday, March 15, 2010 10:19 PM
  • Some more information.  I am using the following binding configuration:
    				<binding name="WSHttpBinding"
    						 closeTimeout="01:00:00"
    						 openTimeout="01:00:00"
    						 receiveTimeout="01:00:00"
    						 sendTimeout="01:00:00"
    						 bypassProxyOnLocal="false"
    						 transactionFlow="false"
    						 hostNameComparisonMode="StrongWildcard"
    						 maxBufferPoolSize="2147483647"
    						 maxReceivedMessageSize="2147483647"
    						 messageEncoding="Text"
    						 textEncoding="utf-8"
    						 useDefaultWebProxy="true"
    						 allowCookies="false">
    					<readerQuotas maxDepth="32"
    								  maxStringContentLength="2147483647"
    								  maxArrayLength="2147483647"
    								  maxBytesPerRead="4096"
    								  maxNameTableCharCount="16384" />
    					<reliableSession ordered="true"
    									 inactivityTimeout="01:00:00"
    									 enabled="true" />
    					<security mode="Message">
    						<transport clientCredentialType="Windows"
    								   proxyCredentialType="None"
    								   realm="" />
    						<message clientCredentialType="Windows"
    								 negotiateServiceCredential="true"
    								 algorithmSuite="Default"
    								 establishSecurityContext="true" />
    					</security>
    				</binding>
    

     

    I have noticed that after uploading and applying all batched changes (set to 256KB) when end session is called on the proxy the following error is returned:

    The underlying secure session has faulted before the reliable session fully completed. The reliable session was faulted.

    What I don't understand is that nothing threw and exception on the server?  I stepped through the server code in the same process. 

    Also, all changes actually get applied to the server.  What could be prematurely ending the WCF session?

    Thanks!
    Stewart

    Tuesday, March 16, 2010 12:16 AM
  • Russell,

    I have also seen this a lot.

    The default values for maxConcurrentCallsmaxConcurrentSessions and MaxConcurrentInstances are 16, 10 and 26 respectively. You have not specified these in the service behavior and so I would suspect that you are having some issues because of these.

    Check out: http://www.danrigsby.com/blog/index.php/2008/02/20/how-to-throttle-a-wcf-service-help-prevent-dos-attacks-and-maintain-wcf-scalability/ as well as http://csharp-codesamples.com/2009/04/configuring-wcf-throttling-behaviors/ for some more info on these.

    Steve

    Tuesday, March 16, 2010 2:30 AM
  • I tried your suggestion but didn't have any luck.  I have create an entire solution that I can share that creates the problem.  To get it to work locally all you should need to do is set a sql account in the web.config file that actually exists and can create databases.

    The app is simple.  Just click each button in order from top to bottom.  When I click the sync button the service always faults before the call to EndSession.  I can't figure out why.  Hopefully someone can review this and see why.  There is some code in here that is extraneous.  I was trying to match the structure of the application we are working in.  The two sync projects are all you should need to focus on (and the WebService project).

    http://cid-8490c2007f0b463b.skydrive.live.com/self.aspx/Public/SyncFramework20NTier.zip

    Thanks to any who take the time to see if they get the same error!!

    Stewart
    Wednesday, March 17, 2010 12:24 AM
  • Stewart,

    I still think that it likely has to do with the maxConcurrentSession setting. If you have followed the examples that MSFT provides, it is my opinion that you will have the problem that you are seeing at some point.

    The reason is, and take as an example the Peer-Peer (the sample named DatabaseSyncP2PoverWCF), that the Cleanup() method on the contract is never called - check out the trace provided by the server side. More specifically, the dispose() method of the proxy on the client side is never called.

    This code is in RelationalProviderProxy.cs and is:

            #region IDisposable Members
    
            public void Dispose()
            {
                this.proxy.Cleanup();
                this.proxy = null;
                GC.SuppressFinalize(this);
            }
    
            #endregion
    


    As you can see, this calls the Cleanup() method on the contract and and destroys the (unmanaged) proxy. Ignoring that this disposal code does not follow that recommended by MSFT (see http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx, "Implementing a dispose() method), this means that you never actally deal with tearing the channel down on either end.

    Well, you need to call this method. Something like this:

                    SqlSyncProvider localProvider = this.CreateLocalProvider(scope);
    
                    RemoteProviderProxy remoteProvider = this.CreateRemoteProviderProxy(scope);
                    
                    SyncOrchestrator syncOrchestrator = this.CreateSyncOrchestrator(localProvider, remoteProvider, direction);
    
                    SyncOperationStatistics stats = syncOrchestrator.Synchronize();
    
                    remoteProvider.Dispose();
    
                    remoteProvider = null;
                    localProvider = null;
                    
                    
    And that is why I think one ends up with issues with using the examples of WCF that have been provided when you do a lot of stuff.

    Of course, you may have already figured this one out or not coded according to the MSFT examples.

    Regarding the disposal, I think something like this is more in line with the MSFT recommended pattern:

            #region IDisposable Members
    
            private bool _disposed = false;
    
            public new void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            private new void Dispose(bool disposing)
            {
                if (!this._disposed)
                {
    
                    this._iProxy.Cleanup();
                    this._iProxy = null;
    
                    this._disposed = true;
    
                    if (disposing)
                    {
                        base.Dispose();
                    }
                }
            }
            #endregion
    




    Steve
    Wednesday, March 17, 2010 1:29 AM
  • No errors for me.

    I noticed you have different values in the config for your timeouts than the one on the server. have you tried changing them to match the server?
    Wednesday, March 17, 2010 1:30 AM
  • Just as a followup, if you have a destructor on the service side, you will now see that it gets called, whereas when the Cleanup() was executed, this did not happen normally.

    I just did 5 different scopes in a row. Below is the trace. Although this was for a sync'd database, what you can see is that although this was a series of 5 sequential syncs, not all of the destruction occurs serially, so for one concurrent sync, you need more that one concurrent session available (at 9:30:31, there were 3 destructors called in a row).

    9:30:14 PM (6): SyncVCService Constructor called
    9:30:14 PM (6): Method Initialize() called: scopeName: <edited out>
    9:30:15 PM (6): Method BeginSession() called: Position: Remote: **** New Session ****
    9:30:18 PM (6): Method GetChanges() called
    9:30:18 PM (6): Method EndSession() called: **** End Sync Session ****
    9:30:18 PM (7): Method BeginSession() called: Position: Remote: **** New Session ****
    9:30:18 PM (7): Method GetKnowledge() called
    9:30:19 PM (7): Method ApplyChanges() called: Resolution Policy: ApplicationDefined
    9:30:19 PM (7): Method EndSession() called: **** End Sync Session ****
    9:30:23 PM (7): Method Cleanup() called
    9:30:24 PM (7): SyncVCService Constructor called
    9:30:24 PM (7): Method Initialize() called: scopeName: <edited out>
    9:30:24 PM (7): Method BeginSession() called: Position: Remote: **** New Session ****
    9:30:24 PM (7): Method GetChanges() called
    9:30:25 PM (2): SyncVCService Destructor called
    9:30:25 PM (7): Method EndSession() called: **** End Sync Session ****
    9:30:25 PM (7): Method BeginSession() called: Position: Remote: **** New Session ****
    9:30:25 PM (7): Method GetKnowledge() called
    9:30:25 PM (7): Method ApplyChanges() called: Resolution Policy: ApplicationDefined
    9:30:26 PM (7): Method EndSession() called: **** End Sync Session ****
    9:30:26 PM (7): Method Cleanup() called
    9:30:26 PM (6): SyncVCService Constructor called
    9:30:26 PM (6): Method Initialize() called: scopeName: <edited out>
    9:30:26 PM (6): Method BeginSession() called: Position: Remote: **** New Session ****
    9:30:27 PM (6): Method GetChanges() called
    9:30:27 PM (6): Method EndSession() called: **** End Sync Session ****
    9:30:27 PM (6): Method BeginSession() called: Position: Remote: **** New Session ****
    9:30:27 PM (6): Method GetKnowledge() called
    9:30:28 PM (6): Method ApplyChanges() called: Resolution Policy: ApplicationDefined
    9:30:28 PM (6): Method EndSession() called: **** End Sync Session ****
    9:30:28 PM (6): Method Cleanup() called
    9:30:29 PM (6): SyncVCService Constructor called
    9:30:29 PM (6): Method Initialize() called: scopeName: <edited out>
    9:30:29 PM (6): Method BeginSession() called: Position: Remote: **** New Session ****
    9:30:29 PM (6): Method GetChanges() called
    9:30:29 PM (6): Method EndSession() called: **** End Sync Session ****
    9:30:29 PM (6): Method BeginSession() called: Position: Remote: **** New Session ****
    9:30:29 PM (6): Method GetKnowledge() called
    9:30:30 PM (6): Method ApplyChanges() called: Resolution Policy: ApplicationDefined
    9:30:30 PM (6): Method EndSession() called: **** End Sync Session ****
    9:30:30 PM (7): Method Cleanup() called
    9:30:30 PM (7): SyncVCService Constructor called
    9:30:30 PM (7): Method Initialize() called: scopeName: <edited out>
    9:30:31 PM (2): SyncVCService Destructor called
    9:30:31 PM (2): SyncVCService Destructor called
    9:30:31 PM (2): SyncVCService Destructor called
    9:30:31 PM (7): Method BeginSession() called: Position: Remote: **** New Session ****
    9:30:31 PM (7): Method GetChanges() called
    9:30:31 PM (7): Method EndSession() called: **** End Sync Session ****
    9:30:31 PM (7): Method BeginSession() called: Position: Remote: **** New Session ****
    9:30:31 PM (7): Method GetKnowledge() called
    9:30:32 PM (7): Method ApplyChanges() called: Resolution Policy: ApplicationDefined
    9:30:32 PM (7): Method EndSession() called: **** End Sync Session ****
    9:30:32 PM (7): Method Cleanup() called
    

    FWIW, this is hosted in IIS 6.0.

    HTH

    Steve
    Wednesday, March 17, 2010 1:41 AM
  • Thanks for the response.  I added the following to my service behaviour (I switched back to the app.config definition from the sample I posted):

    				<behavior name="SyncFramework20NTier.Sync.Server.SyncWebServiceBehavior">
    					<serviceMetadata httpGetEnabled="true" />
    					<serviceThrottling maxConcurrentCalls="100" maxConcurrentSessions="100"/>
    					<serviceDebug includeExceptionDetailInFaults="true" />
    				</behavior>
    

    I still get the error. 

    I also walked through the code (both client and server) as well and verified that only 3 calls were made to the web service before it falted (I restarted IIS before the first call as well).
    1. proxy.Initialize, 2. proxy.BeginSession, and 3. proxy.GetChanges

    It then errored on 4. proxy.EndSession(); because the service was in a faulted state.

    Error: The underlying secure session has faulted before the reliable session fully completed. The reliable session was faulted.

    Any other ideas?  Were you able to recreate the issue locally with my sample?

    http://cid-8490c2007f0b463b.skydrive.live.com/self.aspx/Public/SyncFramework20NTier.zip

    Thanks!
    Stewart

    Wednesday, March 17, 2010 1:46 AM
  • Here is teh stack trace from the server:
    System.ServiceModel.Dispatcher.ErrorBehavior.ThrowAndCatch(Exception e, Message message)
    System.ServiceModel.Channels.DatagramChannelDemuxer`2.ProcessItem(TInnerItem item)
    System.ServiceModel.Channels.DatagramChannelDemuxer`2.HandleReceiveResult(IAsyncResult result)
    System.ServiceModel.Channels.DatagramChannelDemuxer`2.OnReceiveCompleteStatic(IAsyncResult result)
    System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
    System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
    System.ServiceModel.Channels.ReplyChannel.HelpReceiveRequestAsyncResult.OnReceiveRequest(IAsyncResult result)
    System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
    System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
    System.ServiceModel.Channels.InputQueue`1.AsyncQueueReader.Set(Item item)
    System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
    System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(T item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
    System.ServiceModel.Channels.InputQueueChannel`1.EnqueueAndDispatch(TDisposable item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
    System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread)
    System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, ItemDequeuedCallback callback)
    System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
    System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
    System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
    System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
    System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2()
    System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke()
    System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks()
    System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback(Object state)
    System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
    System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
    System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
    
    Wednesday, March 17, 2010 2:14 AM
  • JuneT - Thanks for giving it a go!  Were you able to perform mutliple syncs?  It works for me on the first time you sync.  After that it no longer works.
    Wednesday, March 17, 2010 2:32 AM
  • Russell,

    Have you tried WCF tracing to see what's going on. I have found this to be very useful. It usually identifies the cause of the faults which then leads to quick cures.

    Here is a sample. it goes into the app.config inside the <configuration /> section.

    Steve

    <!-- ============================================================
    
           Diagnostics - used to write into a standard WCF trace file
    
           ============================================================ -->
    
      <system.diagnostics>
        <sources>
          
          <source name="System.ServiceModel.MessageLogging">
            <listeners>
              <add name="messages"
                   type="System.Diagnostics.XmlWriterTraceListener"
                   initializeData="c:\temp\ApplicationNameTester.svclog" />
            </listeners>
          </source>
    
          <source name="System.ServiceModel"
                  switchValue="Verbose,ActivityTracing"
                  propagateActivity="true"
                  >
            <listeners>
              <add type="System.Diagnostics.DefaultTraceListener"
                   name="Default"
                   >
                <filter type="" />
              </add>
              <add name="ServiceModelTraceListener">
                <filter type="" />
              </add>
            </listeners>
          </source>
          
        </sources>
    
        <sharedListeners>
          <add initializeData="C:\temp\TraceApplicationNameTester.svclog"
               type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
               name="ServiceModelTraceListener"
               traceOutputOptions="Timestamp"
               >
            <filter type="" />
          </add>
        </sharedListeners>
    
        <trace autoflush="true" />
    
      </system.diagnostics>
    

    Wednesday, March 17, 2010 2:57 AM
  • Steve -
    Thanks for the help!  I have been looking at the traces but unfortunately, I have had a real hard time making heads or tails of them.  I took your configuration listed above and ran it while I got the error.  I cleaned my computer name out and uploaded them to here. 

    http://cid-8490c2007f0b463b.skydrive.live.com/self.aspx/Public/Traces.zip

    If you have a moment to take a look at them and let me know what I am missing I would be truly in debt to you.

    Thanks!
    Stewart
    Wednesday, March 17, 2010 3:26 AM
  • Stewart,

    Looks like you have the server end traced here.

    From ApplicationNameTester.svclog (which is a trace of the messages going backwards and forwards):
    --> Initialize request
    <-- Initialize response - looks ok
    --> GetScopeDescription request
    <-- GetScopeDescription response - looks ok
    --> BeginSession request, position = remote
    <-- BeginSession response
    --> GetChanges request, batchsize=256
    <-- GetChanges response, looks ok - (timestamp is 11:00:45)
    From xxxxxxx-ApplicationNametester.svclog (which comes after the above)
    --> EndSession
    <-- Fault...see below.

    Ok, so the question is why did things stop after the getchanges response? Looking in TraceApplicationName.svclog at 11:00:45... It just looks like the session is coming down.

    So what you  now need to do is put the same tracing into the client end to see what it is doing with the GetChanges response.

    Steve





    Fault text:

    The message could not be processed. This is most likely because the action 'http://tempuri.org/ISyncWebService/EndSession' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding.

    Wednesday, March 17, 2010 4:15 AM
  • Steve -
    Thanks again!  I have uploaded the trace from the client. 

    http://cid-8490c2007f0b463b.skydrive.live.com/self.aspx/Public/TraceApplicationNameTesterClean.zip

    It looks like something is wrong in the security settings:

    Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties.   This can occur if the service is configured for security and the client is not using security.

    I have no idea what is causing this.  The one thing that is different from the first sync and the failing ones is that the GetChanges call returns no changes for batching.

    Any help would be much appreciated as always!

    Also, I ran the app on my home computer and got the same error.  That helps rule out any firewall issues.  It's also a Vista x64 where my work is a XP x86 with latest sp.

    Thanks!
    Stewart
    Wednesday, March 17, 2010 1:46 PM
  • JuneT - Thanks for giving it a go!  Were you able to perform mutliple syncs?  It works for me on the first time you sync.  After that it no longer works.

    Too quick on my reply. I ran into the problems on my 4 or 5th try I think.

    The error occurs when no changes are downloaded. I havent gone back to check again.
    Wednesday, March 17, 2010 2:17 PM
  • Steve -
    My last upload for the trace wan't complete.  Here is a full trace set from both the server and client.

    http://cid-8490c2007f0b463b.skydrive.live.com/self.aspx/Public/TracesEndToEnd.zip

    Thanks!
    Stewart
    Wednesday, March 17, 2010 2:38 PM
  • JuneT -
    That's what I am noticing as well (Error when no changes).  Any idea what might be causing this?
    Thanks!
    Stewart
    Wednesday, March 17, 2010 2:39 PM
  • Stewart,

    If it was a WCF security error, I don't think you'd be getting through several application-level (i.e. your contract) exchanges.

    Nevertheless, the WCF is throwing this security exception:

    Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties.   This can occur if the service is configured for security and the client is not using security.

    But this is after you have done the following exchange:

    --> Initialize
    <-- response
    --> GetScopeDescription
    <-- response
    --> BeginSession
    <-- response
    --> GetChanges
    <-- response
    --> EndSession
    <-- response
    <security exception is here>
    <tears down channel>

    So, basically upon receiving the GetChanges response, the client side (probably the proxy) sends an EndSession.

    This really seems like you have a problem in the handling of the GetChanges response.

    You can see response this in ApplicationNameTester.svclog, in the 2nd to last activity (a4755ce...), in the 2nd of 3 message log trace records (in the formatted Message Log you will see the method is GetChangesResponse). Now click the XML tab. You will see that there is an empty dataset and the SyncProgress for the 3 tables in the scope (DataLink, DataObject, DataBlob) all show 0 values for all counters, so a cursory observation is that this is ok.

    I'd carefully step through the handling of the GetChanges part of the proxy. If it does not come back out of the call the yourproxyname.GetChanges(..), then I would suspect that it is an issue of deserialization and a problem with contract not being the same at each end. I once had an issue with name spaces on a WCF contract. However, since you are trying to get this to work out of the box, that is probably not the issue.

    Sorry I cannot help any more with the info I have.

    Steve
    Wednesday, March 17, 2010 4:33 PM
  • Steve -
    This is great!  It's right along the lines of what I was thinking.  I thought there might be some sort of deserialization problem with the result of the GetChanges call when it is empty.  Either that or there is something erroring on the server that is causing the server to close the service host.  Do you have any idea how to root out what exactly is causing the server to close the ServiceHost?

    I debugged through the client side proxy's call to GetChagnes.  The GetChangesParameters result seems fine.  Nothing is null in it.  Could there be something wrong in the contract definition?

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Synchronization;
    using System.ServiceModel;
    using Microsoft.Synchronization.Data;
    using System.Runtime.Serialization;
    using System.Data;
    
    namespace SyncFramework20NTier.Sync.Server
    {
    	[ServiceContract(SessionMode = SessionMode.Required)]
    	[ServiceKnownType(typeof(SyncIdFormatGroup))]
    	[ServiceKnownType(typeof(DbSyncContext))]
    	[ServiceKnownType(typeof(SyncSchema))]
    	[ServiceKnownType(typeof(SyncWebServiceFaultException))]
    	[ServiceKnownType(typeof(SyncBatchParameters))]
    	[ServiceKnownType(typeof(GetChangesParameters))]
    	public interface ISyncWebService
    	{
    		[OperationContract(IsInitiating = true)]
    		[FaultContract(typeof(SyncWebServiceFaultException))]
    		void Initialize();
    
    		[OperationContract]
    		[FaultContract(typeof(SyncWebServiceFaultException))]
    		void BeginSession(SyncProviderPosition position);
    
    		[OperationContract]
    		[FaultContract(typeof(SyncWebServiceFaultException))]
    		SyncBatchParameters GetKnowledge();
    
    		[OperationContract]
    		[FaultContract(typeof(SyncWebServiceFaultException))]
    		GetChangesParameters GetChanges(uint batchSize, SyncKnowledge destinationKnowledge);
    
    		[OperationContract]
    		[FaultContract(typeof(SyncWebServiceFaultException))]
    		SyncSessionStatistics ApplyChanges(ConflictResolutionPolicy resolutionPolicy, ChangeBatch sourceChanges, object changeData);
    
    		[OperationContract]
    		[FaultContract(typeof(SyncWebServiceFaultException))]
    		bool HasUploadedBatchFile(string batchFileid, string remotePeerId);
    
    		[OperationContract]
    		[FaultContract(typeof(SyncWebServiceFaultException))]
    		void UploadBatchFile(string batchFileid, byte[] batchFile, string remotePeerId);
    
    		[OperationContract]
    		[FaultContract(typeof(SyncWebServiceFaultException))]
    		byte[] DownloadBatchFile(string batchFileId);
    
    		[OperationContract]
    		[FaultContract(typeof(SyncWebServiceFaultException))]
    		void EndSession();
    
    		[OperationContract(IsTerminating = true)]
    		[FaultContract(typeof(SyncWebServiceFaultException))]
    		void Cleanup();
    
    		[OperationContract]
    		[FaultContract(typeof(SyncWebServiceFaultException))]
    		DbSyncScopeDescription GetScopeDescription();
    	}
    
    	[DataContract()]
    	public class SyncBatchParameters
    	{
    		[DataMember]
    		public SyncKnowledge DestinationKnowledge;
    
    		[DataMember]
    		public uint BatchSize;
    	}
    
    	[DataContract()]
    	[KnownType(typeof(DataSet))]
    	public class GetChangesParameters
    	{
    		[DataMember]
    		public object DataRetriever;
    
    		[DataMember]
    		public ChangeBatch ChangeBatch;
    	}
    }
    

     

    Thanks AGAIN!

    Stewart

    Wednesday, March 17, 2010 6:05 PM
  • AHH HELLLL YEAH!  I got it!!!!! 

    Turns out it was all related to the location of the BatchingDirectory.  I had it wired to use a folder called Batching under the root of the asp.net application directory.  Appearently, when you do this, and GetChanges does NOT have any results to batch, IIS closes the channel for you after the call to GetChanges.  I changed my batching directory to be somewhere other than under the web service application and its all fixed!  Only took 4 days to figure that out.  Second longest time I have ever spent to resolve one bug.  All works like a charm.  We are ready to roll into QA!

    Thanks again Steve for helping out!  If you can, send me an email at stewart.armbrecht@protiviti.com.  I'd like to give you something for all your effort.
    Wednesday, March 17, 2010 6:50 PM
  • Hi

    We have Implemented data syncing successfully and it works fine for some clients and for the rest we are facing a problem in syncing a particular table which is quite large, every other table in the database are under sync without any errors. We enabled the trace on the server and we fond some errors:

    ·         Type 'Microsoft.Synchronization.Data.DbSyncException' with data contract name 'DbSyncException:http://schemas.datacontract.org/2004/07/Microsoft.Synchronization.Data' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

    ·        
    The communication object, System.ServiceModel.Channels.ReplyChannel, cannot be used for communication because it has been Aborted.

    ·         There was no channel that could accept the message with action 'http://tempuri.org/ISyncWebService/BeginSession'.

    ·         The communication object, System.ServiceModel.Channels.TransportReplyChannelAcceptor+TransportReplyChannel, cannot be used for communication because it has been Aborted

      Any help would be really appreciated.

    Thursday, April 14, 2011 6:45 AM