Answered by:
Microsoft.Synchronization.ChangeBatch.DeserializeHelper Failure

Question
-
We've been using Sync V2 RTM in our project for quite some time now, but when I set the FilterKeyMap property of the ChangeBatch, we are no longer able to de-serialize the requests via WCF.I've tried extending FilterKeyMap to provide a default constructor with the correct SyncGroupIdFormats, but that doesn't help.I've also tried passing pre-serialized byte[]'s for all the contract operation, but that just moved the exception into my code instead of the WCF code.Any ideas why FilterKeyMap makes a ChangeBatch impossible to deserialize?Wednesday, February 3, 2010 9:57 PM
Answers
-
If you would like to do a filtered sync, then you need to create a filtered change batch? If so then you need
1. To have a FilterInfo object (such as Microsoft.Synchronization.ItemListFilterInfo) as the 4th parameter in the ChangeBatch constructor.
2. ChangeFilter object needs to have the filter key map defined, as you did already.
3. During Deserialize, you also need to provide an object which can deserialize the filter object. This is the photo type -
public static ChangeBatch Deserialize(SyncIdFormatGroup idFormats, ISyncFilterDeserializer syncFilterDeserializer, byte[] data);
4. And this is a sample of deserializer class.
public class MyFilterDeserializer : ISyncFilterDeserializer
{
public ISyncFilter Deserialize(byte[] data)
{
string filterValue = (new UnicodeEncoding(true, true)).GetString(data);
MyFilter filter = new MyFilter (filterValue);
return (ISyncFilter)filter;
}
}
Thanks.
Leo Zhou ------ This posting is provided "AS IS" with no warranties, and confers no rights.- Proposed as answer by L Zhou [MSFT]Editor Monday, February 8, 2010 11:34 PM
- Marked as answer by Mark Kotyk Tuesday, February 9, 2010 3:39 PM
Monday, February 8, 2010 8:21 PMAnswerer
All replies
-
Here's some code to reproduce my result in its simplest form.static private SyncIdFormatGroup syncIdFormatGroup = null;static public SyncIdFormatGroup IdFormats{get{if (syncIdFormatGroup == null){syncIdFormatGroup = new SyncIdFormatGroup();syncIdFormatGroup.ChangeUnitIdFormat.IsVariableLength = false;syncIdFormatGroup.ChangeUnitIdFormat.Length = 1;syncIdFormatGroup.ReplicaIdFormat.IsVariableLength = false;syncIdFormatGroup.ReplicaIdFormat.Length = 16;syncIdFormatGroup.ItemIdFormat.IsVariableLength = false;syncIdFormatGroup.ItemIdFormat.Length = 20;}return syncIdFormatGroup;}}[Serializable]class MyFilter : ISyncFilter{public bool IsIdentical(ISyncFilter otherFilter){return (otherFilter.GetType().Equals(this.GetType()));}public byte[] Serialize(){System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf= new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();System.IO.MemoryStream memStream = new System.IO.MemoryStream();bf.Serialize(memStream, this);return memStream.GetBuffer();}}public static void ChangeBatchSerializationTest(){Console.WriteLine("Test ChangeBatch and FilterKeyMap serialization");SyncId replicaId = new SyncId(Guid.NewGuid());SyncKnowledge destKnowledge = new SyncKnowledge(IdFormats, replicaId, 0);ForgottenKnowledge sourceForgottenKnowledge = new ForgottenKnowledge(IdFormats, destKnowledge);ChangeBatch changeBatch = new ChangeBatch(IdFormats, destKnowledge, sourceForgottenKnowledge);changeBatch.FilterKeyMap = new Microsoft.Synchronization.FilterKeyMap(IdFormats);// This line doesn't seem to make a difference to the resultchangeBatch.FilterKeyMap.AddFilter(new MyFilter());byte[] serializedChangeBatch = changeBatch.Serialize();try{ChangeBatch rehydratedChangeBatch = ChangeBatch.Deserialize(IdFormats, serializedChangeBatch);}catch (Exception ex){Console.WriteLine("Unable to de-serialize ChangeBatch {0}", ex);}}Thursday, February 4, 2010 10:03 PM
-
If you would like to do a filtered sync, then you need to create a filtered change batch? If so then you need
1. To have a FilterInfo object (such as Microsoft.Synchronization.ItemListFilterInfo) as the 4th parameter in the ChangeBatch constructor.
2. ChangeFilter object needs to have the filter key map defined, as you did already.
3. During Deserialize, you also need to provide an object which can deserialize the filter object. This is the photo type -
public static ChangeBatch Deserialize(SyncIdFormatGroup idFormats, ISyncFilterDeserializer syncFilterDeserializer, byte[] data);
4. And this is a sample of deserializer class.
public class MyFilterDeserializer : ISyncFilterDeserializer
{
public ISyncFilter Deserialize(byte[] data)
{
string filterValue = (new UnicodeEncoding(true, true)).GetString(data);
MyFilter filter = new MyFilter (filterValue);
return (ISyncFilter)filter;
}
}
Thanks.
Leo Zhou ------ This posting is provided "AS IS" with no warranties, and confers no rights.- Proposed as answer by L Zhou [MSFT]Editor Monday, February 8, 2010 11:34 PM
- Marked as answer by Mark Kotyk Tuesday, February 9, 2010 3:39 PM
Monday, February 8, 2010 8:21 PMAnswerer -
It appears item 3 and 4 is the key.A bit unfortunate since I will have to refactor all my WCF interfaces to handle deserialization in my code instead of automatically via WCF.Tuesday, February 9, 2010 3:41 PM