diff --git a/DurableTask.ServiceFabric.sln b/DurableTask.ServiceFabric.sln
index 3307fd48b..245448581 100644
--- a/DurableTask.ServiceFabric.sln
+++ b/DurableTask.ServiceFabric.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.26403.7
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.34301.259
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{501E1168-418C-4832-B88C-617735BD02C9}"
ProjectSection(SolutionItems) = preProject
@@ -51,6 +51,7 @@ Global
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CA924781-AE52-45FA-A817-C39C822FB782}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {CA924781-AE52-45FA-A817-C39C822FB782}.Debug|Any CPU.Build.0 = Debug|x64
{CA924781-AE52-45FA-A817-C39C822FB782}.Debug|x64.ActiveCfg = Debug|x64
{CA924781-AE52-45FA-A817-C39C822FB782}.Debug|x64.Build.0 = Debug|x64
{CA924781-AE52-45FA-A817-C39C822FB782}.Debug|x64.Deploy.0 = Debug|x64
@@ -59,6 +60,7 @@ Global
{CA924781-AE52-45FA-A817-C39C822FB782}.Release|x64.Build.0 = Release|x64
{CA924781-AE52-45FA-A817-C39C822FB782}.Release|x64.Deploy.0 = Release|x64
{95D6C9C7-F7A0-4125-840D-1854BEC24978}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {95D6C9C7-F7A0-4125-840D-1854BEC24978}.Debug|Any CPU.Build.0 = Debug|x64
{95D6C9C7-F7A0-4125-840D-1854BEC24978}.Debug|x64.ActiveCfg = Debug|x64
{95D6C9C7-F7A0-4125-840D-1854BEC24978}.Debug|x64.Build.0 = Debug|x64
{95D6C9C7-F7A0-4125-840D-1854BEC24978}.Release|Any CPU.ActiveCfg = Release|x64
@@ -170,5 +172,6 @@ Global
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EnterpriseLibraryConfigurationToolBinariesPath = packages\TransientFaultHandling.Core.5.1.1209.1\lib\NET4
+ SolutionGuid = {BCE9A2EE-C1D3-4F37-8500-E112D840827F}
EndGlobalSection
EndGlobal
diff --git a/Test/DurableTask.ServiceFabric.Test/AssemblySetup.cs b/Test/DurableTask.ServiceFabric.Test/AssemblySetup.cs
index 9776be272..3271adf52 100644
--- a/Test/DurableTask.ServiceFabric.Test/AssemblySetup.cs
+++ b/Test/DurableTask.ServiceFabric.Test/AssemblySetup.cs
@@ -42,9 +42,9 @@ static string TestApplicationRootPath
{
get
{
- var sourceRoot = Environment.GetEnvironmentVariable("SourceRoot") ?? string.Empty;
- var applicationPath = Path.Combine(sourceRoot.Trim(), "Test", "TestFabricApplication", "TestFabricApplication");
-
+ //var sourceRoot = Environment.GetEnvironmentVariable("SourceRoot") ?? string.Empty;
+ //var applicationPath = Path.Combine(sourceRoot.Trim(), "Test", "TestFabricApplication", "TestFabricApplication");
+ var applicationPath = Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\TestFabricApplication\TestFabricApplication");
if (!Directory.Exists(applicationPath))
{
throw new Exception("Could not find test application path, define SourceRoot environment variable to the source path");
diff --git a/Test/TestFabricApplication/TestFabricApplication/TestFabricApplication.sfproj b/Test/TestFabricApplication/TestFabricApplication/TestFabricApplication.sfproj
index edcf3f147..4234f82d2 100644
--- a/Test/TestFabricApplication/TestFabricApplication/TestFabricApplication.sfproj
+++ b/Test/TestFabricApplication/TestFabricApplication/TestFabricApplication.sfproj
@@ -1,10 +1,11 @@
-
+
ca924781-ae52-45fa-a817-c39c822fb782
- 1.6
+ 2.1
1.5
+ 1.7.6
@@ -38,9 +39,9 @@
$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Service Fabric Tools\Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/Test/TestFabricApplication/TestFabricApplication/packages.config b/Test/TestFabricApplication/TestFabricApplication/packages.config
index c5f59e48e..ad8665e2d 100644
--- a/Test/TestFabricApplication/TestFabricApplication/packages.config
+++ b/Test/TestFabricApplication/TestFabricApplication/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/Test/TestFabricApplication/TestStatefulService/CustomDataContractStateSerializer.cs b/Test/TestFabricApplication/TestStatefulService/CustomDataContractStateSerializer.cs
new file mode 100644
index 000000000..1a92ded0d
--- /dev/null
+++ b/Test/TestFabricApplication/TestStatefulService/CustomDataContractStateSerializer.cs
@@ -0,0 +1,111 @@
+// ----------------------------------------------------------------------------------
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+
+namespace TestStatefulService
+{
+ using System.IO;
+ using System.Runtime.Serialization;
+ using System.Xml;
+ using Microsoft.ServiceFabric.Data;
+
+ internal class CustomDataContractStateSerializer : IStateSerializer
+ {
+ ///
+ /// The serializer.
+ ///
+ private readonly DataContractSerializer serializer = new DataContractSerializer(typeof(T));
+
+ ///
+ /// Converts byte[] to T
+ ///
+ /// Reader containing the serialized data.
+ /// Deserialized version of T.
+ public T Read(BinaryReader binaryReader)
+ {
+ var size = binaryReader.ReadInt32();
+
+ var bytes = binaryReader.ReadBytes(size);
+
+ using (var memoryStream = new MemoryStream(bytes))
+ {
+ using (var reader = XmlDictionaryReader.CreateBinaryReader(memoryStream, XmlDictionaryReaderQuotas.Max))
+ using (var customReader = new CustomerXmlDictionaryReader(reader, typeof(T)))
+ {
+ return (T) this.serializer.ReadObject(customReader);
+ }
+ }
+ }
+
+ ///
+ /// Converts IEnumerable of byte[] to T
+ ///
+ ///
+ /// Reader containing the serialized data.
+ /// Deserialized version of T.
+ public T Read(T baseValue, BinaryReader reader)
+ {
+ return this.Read(reader);
+ }
+
+ ///
+ /// Converts T to byte array.
+ ///
+ /// T to be serialized.
+ ///
+ /// Serialized version of T.
+ public void Write(T value, BinaryWriter binaryWriter)
+ {
+ using (var memoryStream = new MemoryStream())
+ {
+ using (var innerWriter = new BinaryWriter(memoryStream))
+ {
+ innerWriter.Write(int.MinValue);
+
+ using (
+ var binaryDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(
+ memoryStream,
+ null,
+ null,
+ false))
+ {
+ this.serializer.WriteObject(binaryDictionaryWriter, value);
+ binaryDictionaryWriter.Flush();
+ }
+
+ var lastPosition = (int) memoryStream.Position;
+
+ memoryStream.Position = 0;
+
+ innerWriter.Write(lastPosition - sizeof(int));
+
+ memoryStream.Position = lastPosition;
+
+ binaryWriter.Write(memoryStream.GetBuffer(), 0, lastPosition);
+ }
+ }
+ }
+
+ ///
+ /// Converts T to byte array.
+ ///
+ ///
+ /// Writer to which the serialized data should be written.
+ ///
+ /// Serialized version of T.
+ public void Write(T currentValue, T newValue, BinaryWriter binaryWriter)
+ {
+ this.Write(newValue, binaryWriter);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Test/TestFabricApplication/TestStatefulService/CustomerXmlDictionaryReader.cs b/Test/TestFabricApplication/TestStatefulService/CustomerXmlDictionaryReader.cs
new file mode 100644
index 000000000..3774d59de
--- /dev/null
+++ b/Test/TestFabricApplication/TestStatefulService/CustomerXmlDictionaryReader.cs
@@ -0,0 +1,161 @@
+// ----------------------------------------------------------------------------------
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Xml;
+
+namespace TestStatefulService
+{
+ internal class CustomerXmlDictionaryReader : XmlDictionaryReader
+ {
+ XmlDictionaryReader innerReader;
+ Type targetType;
+ bool isTargetV2;
+
+ static IDictionary namespaceMapV1toV2 = new Dictionary
+ {
+ { "DurableTask.ServiceFabric", "DurableTask.AzureServiceFabric" },
+ { "DurableTask", "DurableTask.Core" },
+ { "DurableTask.History", "DurableTask.Core.History" }
+ };
+
+ static IDictionary namespaceMapV2toV1 = new Dictionary
+ {
+ { "DurableTask.AzureServiceFabric", "DurableTask.ServiceFabric" },
+ { "DurableTask.Core", "DurableTask" },
+ { "DurableTask.Core.History", "DurableTask.History" }
+ };
+
+ public CustomerXmlDictionaryReader(XmlDictionaryReader innerReader, Type type)
+ {
+ this.innerReader = innerReader;
+ this.targetType = type;
+
+ this.isTargetV2 = this.targetType.Namespace == "DurableTask.AzureServiceFabric" ? true : false;
+ }
+
+ public override int AttributeCount => this.innerReader.AttributeCount;
+
+ public override string BaseURI => this.innerReader.BaseURI;
+
+ public override int Depth => this.innerReader.Depth;
+
+ public override bool EOF => this.innerReader.EOF;
+
+ public override bool IsEmptyElement => this.innerReader.IsEmptyElement;
+
+ public override string LocalName => this.innerReader.LocalName;
+
+ public override string NamespaceURI
+ {
+ get
+ {
+ // Alter the old namespace
+ UriBuilder builder = new UriBuilder(innerReader.NamespaceURI);
+
+ var segments = builder.Uri.Segments;
+ var mapToUse = namespaceMapV2toV1;
+ string last = segments.LastOrDefault();
+ if (isTargetV2)
+ {
+ mapToUse = namespaceMapV1toV2;
+ }
+
+ if (mapToUse.ContainsKey(last))
+ {
+ segments[segments.Length - 1] = mapToUse[last];
+ builder.Path = String.Join("", segments);
+ //File.AppendAllText(@"D:\git\durabletask\main\Test\TestFabricApplication\TestFabricApplication\SerializationInfo2.txt", $"OLD: {innerReader.NamespaceURI} NEW: {builder.Uri} {this.isTargetV2} {Environment.NewLine}");
+ return builder.Uri.ToString();
+ }
+
+ return innerReader.NamespaceURI;
+ }
+ }
+
+ public override XmlNameTable NameTable => this.innerReader.NameTable;
+
+ public override XmlNodeType NodeType => this.innerReader.NodeType;
+
+ public override string Prefix => this.innerReader.Prefix;
+
+ public override ReadState ReadState => this.innerReader.ReadState;
+
+ public override string Value => this.innerReader.Value;
+
+ public override string GetAttribute(int i)
+ {
+ return this.innerReader.GetAttribute(i);
+ }
+
+ public override string GetAttribute(string name)
+ {
+ return this.innerReader.GetAttribute(name);
+ }
+
+ public override string GetAttribute(string name, string namespaceURI)
+ {
+ return this.innerReader.GetAttribute(name, namespaceURI);
+ }
+
+ public override string LookupNamespace(string prefix)
+ {
+ return this.innerReader.LookupNamespace(prefix);
+ }
+
+ public override bool MoveToAttribute(string name)
+ {
+ return this.innerReader.MoveToAttribute(name);
+ }
+
+ public override bool MoveToAttribute(string name, string ns)
+ {
+ return this.innerReader.MoveToAttribute(name, ns);
+ }
+
+ public override bool MoveToElement()
+ {
+ return this.innerReader.MoveToElement();
+ }
+
+ public override bool MoveToFirstAttribute()
+ {
+ return this.innerReader.MoveToFirstAttribute();
+ }
+
+ public override bool MoveToNextAttribute()
+ {
+ return this.innerReader.MoveToNextAttribute();
+ }
+
+ public override bool Read()
+ {
+ return this.innerReader.Read();
+ }
+
+ public override bool ReadAttributeValue()
+ {
+ return this.innerReader.ReadAttributeValue();
+ }
+
+ public override void ResolveEntity()
+ {
+ this.innerReader.ResolveEntity();
+ }
+ }
+}
diff --git a/Test/TestFabricApplication/TestStatefulService/TestStatefulService.cs b/Test/TestFabricApplication/TestStatefulService/TestStatefulService.cs
index 72c1e0029..27c3cc857 100644
--- a/Test/TestFabricApplication/TestStatefulService/TestStatefulService.cs
+++ b/Test/TestFabricApplication/TestStatefulService/TestStatefulService.cs
@@ -18,6 +18,7 @@
using System.Threading;
using System.Threading.Tasks;
using DurableTask;
+using DurableTask.History;
using DurableTask.ServiceFabric;
using DurableTask.Test.Orchestrations.Perf;
using Microsoft.ServiceFabric.Services.Communication.Runtime;
@@ -49,6 +50,8 @@ public TestStatefulService(StatefulServiceContext context) : base(context)
this.fabricProviderFactory = new FabricOrchestrationProviderFactory(this.StateManager, settings);
this.fabricProvider = this.fabricProviderFactory.CreateProvider();
this.client = new TaskHubClient(fabricProvider.OrchestrationServiceClient);
+
+ this.StateManager.TryAddStateSerializer(new CustomDataContractStateSerializer());
}
///
diff --git a/Test/TestFabricApplication/TestStatefulService/TestStatefulService.csproj b/Test/TestFabricApplication/TestStatefulService/TestStatefulService.csproj
index 70bcc5acb..6f8672019 100644
--- a/Test/TestFabricApplication/TestStatefulService/TestStatefulService.csproj
+++ b/Test/TestFabricApplication/TestStatefulService/TestStatefulService.csproj
@@ -13,6 +13,7 @@
512
true
True
+
true
@@ -113,8 +114,11 @@
..\..\..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll
True
+
+
+
diff --git a/src/DurableTask.ServiceFabric/TaskMessageItem.cs b/src/DurableTask.ServiceFabric/TaskMessageItem.cs
index 55ff3d129..896f5be87 100644
--- a/src/DurableTask.ServiceFabric/TaskMessageItem.cs
+++ b/src/DurableTask.ServiceFabric/TaskMessageItem.cs
@@ -16,17 +16,29 @@ namespace DurableTask.ServiceFabric
using System;
using System.Runtime.Serialization;
+ ///
+ /// This wrapper is used with Service Fabric collections to persist TaskMessage.
+ ///
[DataContract]
- sealed class TaskMessageItem : IExtensibleDataObject
+ public sealed class TaskMessageItem : IExtensibleDataObject
{
+ ///
+ /// This wrapper is used with Service Fabric collections to persist TaskMessage.
+ ///
public TaskMessageItem(TaskMessage taskMessage)
{
this.TaskMessage = taskMessage ?? throw new ArgumentNullException(nameof(taskMessage));
}
+ ///
+ /// TaskMessage defined in TaskHub Core.
+ ///
[DataMember]
public TaskMessage TaskMessage { get; private set; }
+ ///
+ /// TaskMessage ExtensionData.
+ ///
public ExtensionDataObject ExtensionData { get; set; }
}
}