diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs
index 131c6c8203..310616198c 100644
--- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs
+++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs
@@ -6,18 +6,18 @@ namespace Microsoft.Azure.Cosmos
{
using System;
using System.Collections;
- using System.Threading;
+ using System.Runtime.Serialization;
using global::Azure.Core.Pipeline;
using Microsoft.Azure.Cosmos.Diagnostics;
using Microsoft.Azure.Cosmos.Telemetry;
- using Microsoft.Azure.Cosmos.Telemetry.Diagnostics;
using Microsoft.Azure.Cosmos.Tracing;
///
/// The exception that is thrown in a thread upon cancellation of an operation that
/// the thread was executing. This extends the OperationCanceledException to include the
/// diagnostics of the operation that was canceled.
- ///
+ ///
+ [Serializable]
public class CosmosOperationCanceledException : OperationCanceledException
{
private readonly OperationCanceledException originalException;
@@ -63,6 +63,22 @@ internal CosmosOperationCanceledException(
this.lazyMessage = this.CreateLazyMessage();
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The SerializationInfo object that holds serialized object data for the exception being thrown.
+ /// The StreamingContext that contains contextual information about the source or destination.
+ protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ this.originalException = (OperationCanceledException)info.GetValue("originalException", typeof(OperationCanceledException));
+ this.tokenCancellationRequested = (bool)info.GetValue("tokenCancellationRequested", typeof(bool));
+ this.lazyMessage = new Lazy(() => (string)info.GetValue("lazyMessage", typeof(string)));
+ this.toStringMessage = new Lazy(() => (string)info.GetValue("toStringMessage", typeof(string)));
+ //Diagnostics cannot be serialized
+ this.Diagnostics = new CosmosTraceDiagnostics(NoOpTrace.Singleton);
+ }
+
///
public override string Source
{
@@ -111,7 +127,7 @@ private Lazy CreateToStringMessage()
{
return new Lazy(() => $"{this.originalException}{Environment.NewLine}Cancellation Token has expired: {this.tokenCancellationRequested}. Learn more at: https://aka.ms/cosmosdb-tsg-request-timeout{Environment.NewLine}CosmosDiagnostics: {this.Diagnostics}");
}
-
+
///
/// RecordOtelAttributes
///
@@ -123,5 +139,19 @@ internal static void RecordOtelAttributes(CosmosOperationCanceledException excep
scope.AddAttribute(OpenTelemetryAttributeKeys.RequestDiagnostics, exception.Diagnostics);
scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionMessage, exception.GetBaseException().Message);
}
+
+ ///
+ /// Sets the System.Runtime.Serialization.SerializationInfo with information about the exception.
+ ///
+ /// The SerializationInfo object that holds serialized object data for the exception being thrown.
+ /// The StreamingContext that contains contextual information about the source or destination.
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ info.AddValue("originalException", this.originalException);
+ info.AddValue("tokenCancellationRequested", this.tokenCancellationRequested);
+ info.AddValue("lazyMessage", this.lazyMessage.Value);
+ info.AddValue("toStringMessage", this.toStringMessage.Value);
+ }
}
}
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json
index bc28d53536..1a69454b04 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json
@@ -3259,7 +3259,7 @@
},
"NestedTypes": {}
},
- "Microsoft.Azure.Cosmos.CosmosOperationCanceledException;System.OperationCanceledException;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": {
+ "Microsoft.Azure.Cosmos.CosmosOperationCanceledException;System.OperationCanceledException;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": {
"Subclasses": {},
"Members": {
"Microsoft.Azure.Cosmos.CosmosDiagnostics Diagnostics": {
@@ -3339,6 +3339,11 @@
"Attributes": [],
"MethodInfo": "[Void .ctor(System.OperationCanceledException, Microsoft.Azure.Cosmos.CosmosDiagnostics), Void .ctor(System.OperationCanceledException, Microsoft.Azure.Cosmos.CosmosDiagnostics)]"
},
+ "Void GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)": {
+ "Type": "Method",
+ "Attributes": [],
+ "MethodInfo": "Void GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
+ },
"Void set_HelpLink(System.String)": {
"Type": "Method",
"Attributes": [],
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs
new file mode 100644
index 0000000000..5262c2b343
--- /dev/null
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs
@@ -0,0 +1,39 @@
+//------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------
+
+namespace Microsoft.Azure.Cosmos.Tests
+{
+ using System;
+ using Microsoft.Azure.Cosmos.Diagnostics;
+ using Microsoft.Azure.Cosmos.Tracing;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using Newtonsoft.Json;
+
+ [TestClass]
+ public class CosmosOperationCanceledTests
+ {
+
+ [TestMethod]
+ public void SerializationValidation()
+ {
+ //create test exception
+ CosmosOperationCanceledException originalException = new CosmosOperationCanceledException(
+ new OperationCanceledException("error message"),
+ new CosmosTraceDiagnostics(NoOpTrace.Singleton));
+
+ //serialize exception
+ string serialized = JsonConvert.SerializeObject(originalException);
+
+ CosmosOperationCanceledException deserializedExceptoin =
+ JsonConvert.DeserializeObject(serialized);
+
+ //Asserts
+ Assert.AreEqual(originalException.ToString(), deserializedExceptoin.ToString());
+ Assert.AreEqual(originalException.Message, deserializedExceptoin.Message);
+ Assert.AreEqual(originalException.GetBaseException().Message, deserializedExceptoin.GetBaseException().Message);
+ Assert.AreEqual(originalException.GetBaseException().ToString(), deserializedExceptoin.GetBaseException().ToString());
+ Assert.AreEqual(originalException.GetBaseException().HResult, deserializedExceptoin.GetBaseException().HResult);
+ }
+ }
+}