diff --git a/src/csharp/Grpc.Core.Api/Status.cs b/src/csharp/Grpc.Core.Api/Status.cs
index 72d9e5371b8..32f79f74cc1 100644
--- a/src/csharp/Grpc.Core.Api/Status.cs
+++ b/src/csharp/Grpc.Core.Api/Status.cs
@@ -14,6 +14,8 @@
// limitations under the License.
#endregion
+using System;
+
namespace Grpc.Core
{
///
@@ -47,12 +49,12 @@ namespace Grpc.Core
///
/// Status code.
/// Detail.
- /// Optional internal error string.
- public Status(StatusCode statusCode, string detail, string debugErrorString)
+ /// Optional internal error details.
+ public Status(StatusCode statusCode, string detail, Exception debugErrorException)
{
StatusCode = statusCode;
Detail = detail;
- DebugErrorString = debugErrorString;
+ DebugErrorException = debugErrorException;
}
///
@@ -70,20 +72,20 @@ namespace Grpc.Core
/// This field will be only populated on a client and its value is generated locally,
/// based on the internal state of the gRPC client stack (i.e. the value is never sent over the wire).
/// Note that this field is available only for debugging purposes, the application logic should
- /// never rely on values of this field (it should should StatusCode and Detail instead).
+ /// never rely on values of this field (it should use StatusCode and Detail instead).
/// Example: when a client fails to connect to a server, this field may provide additional details
/// why the connection to the server has failed.
///
- public string DebugErrorString { get; }
+ public Exception DebugErrorException { get; }
///
/// Returns a that represents the current .
///
public override string ToString()
{
- if (DebugErrorString != null)
+ if (DebugErrorException != null)
{
- return $"Status(StatusCode=\"{StatusCode}\", Detail=\"{Detail}\", DebugErrorString=\"{DebugErrorString}\")";
+ return $"Status(StatusCode=\"{StatusCode}\", Detail=\"{Detail}\", DebugErrorException=\"{DebugErrorException}\")";
}
return $"Status(StatusCode=\"{StatusCode}\", Detail=\"{Detail}\")";
}
diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index a12ed31e95d..7072851732a 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -144,18 +144,18 @@ namespace Grpc.Core.Tests
{
helper.UnaryHandler = new UnaryServerMethod((request, context) =>
{
- context.Status = new Status(StatusCode.Unauthenticated, "", "this DebugErrorString value should not be transmitted to the client");
+ context.Status = new Status(StatusCode.Unauthenticated, "", new DebugErrorException("this DebugErrorString value should not be transmitted to the client"));
return Task.FromResult("");
});
var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode);
- StringAssert.Contains("Error received from peer", ex.Status.DebugErrorString, "Is \"Error received from peer\" still a valid substring to search for in the client-generated error message from C-core?");
+ StringAssert.Contains("Error received from peer", ex.Status.DebugErrorException.Message, "Is \"Error received from peer\" still a valid substring to search for in the client-generated error message from C-core?");
Assert.AreEqual(0, ex.Trailers.Count);
var ex2 = Assert.ThrowsAsync(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc"));
Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode);
- StringAssert.Contains("Error received from peer", ex2.Status.DebugErrorString, "Is \"Error received from peer\" still a valid substring to search for in the client-generated error message from C-core?");
+ StringAssert.Contains("Error received from peer", ex2.Status.DebugErrorException.Message, "Is \"Error received from peer\" still a valid substring to search for in the client-generated error message from C-core?");
Assert.AreEqual(0, ex2.Trailers.Count);
}
diff --git a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
index a8470af549e..e00f153c21f 100644
--- a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
@@ -93,7 +93,7 @@ namespace Grpc.Core.Internal
IntPtr detailsPtr = Native.grpcsharp_batch_context_recv_status_on_client_details(this, out detailsLength);
string details = MarshalUtils.PtrToStringUTF8(detailsPtr, (int)detailsLength.ToUInt32());
string debugErrorString = Marshal.PtrToStringAnsi(Native.grpcsharp_batch_context_recv_status_on_client_error_string(this));
- var status = new Status(Native.grpcsharp_batch_context_recv_status_on_client_status(this), details, debugErrorString);
+ var status = new Status(Native.grpcsharp_batch_context_recv_status_on_client_status(this), details, debugErrorString != null ? new DebugErrorException(debugErrorString) : null);
IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_recv_status_on_client_trailing_metadata(this);
var metadata = MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr);
diff --git a/src/csharp/Grpc.Core/Internal/DebugErrorException.cs b/src/csharp/Grpc.Core/Internal/DebugErrorException.cs
new file mode 100644
index 00000000000..a8c4561c4bf
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/DebugErrorException.cs
@@ -0,0 +1,35 @@
+#region Copyright notice and license
+
+// Copyright 2019 The gRPC Authors
+//
+// 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.
+
+#endregion
+
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core.Internal
+{
+ ///
+ /// Represents error details provides by C-core's debug_error_string
+ ///
+ internal class DebugErrorException : Exception
+ {
+ public DebugErrorException(string message) : base(message)
+ {
+ }
+ }
+}