diff --git a/src/csharp/Grpc.Core/Calls.cs b/src/csharp/Grpc.Core/Calls.cs
index c0973234e2ac27a1c37ab44b4fc206495515e031..ee2208e5c255768715cca2f2045f17d37a060bcc 100644
--- a/src/csharp/Grpc.Core/Calls.cs
+++ b/src/csharp/Grpc.Core/Calls.cs
@@ -49,20 +49,6 @@ namespace Grpc.Core
         {
             var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestSerializer, call.ResponseDeserializer);
             return asyncCall.UnaryCall(call.Channel, call.MethodName, req);
-
-            //TODO: implement this in real synchronous style.
-//            try {
-//                return AsyncUnaryCall(call, req, token).Result;
-//            } catch(AggregateException ae) {
-//                foreach (var e in ae.InnerExceptions)
-//                {
-//                    if (e is RpcException)
-//                    {
-//                        throw e;
-//                    }
-//                }
-//                throw;
-//            }
         }
 
         public static async Task<TResponse> AsyncUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 664d534dc29cde874761369c9bf967e5852bf48c..135ce26cbd23500f8dc500670a594edd3c9d85ed 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -63,6 +63,7 @@
     <Compile Include="Internal\ServerStreamingOutputObserver.cs" />
     <Compile Include="Internal\BatchContextSafeHandleNotOwned.cs" />
     <Compile Include="Utils\BenchmarkUtil.cs" />
+    <Compile Include="Utils\ExceptionHelper.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
index 7c40661cf4b4289f774823733abab9f9f16b2823..dadc9ab76cf5c5125511774da04d0dfc3fec357f 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
@@ -38,6 +38,7 @@ using System.Runtime.InteropServices;
 using System.Threading;
 using System.Threading.Tasks;
 using Grpc.Core.Internal;
+using Grpc.Core.Utils;
 
 namespace Grpc.Core.Internal
 {
@@ -130,10 +131,15 @@ namespace Grpc.Core.Internal
                 }
                 call.BlockingUnary(cq, payload, unaryResponseHandler);
 
-                // task should be finished once BlockingUnary returns.
-                return unaryResponseTcs.Task.Result;
-
-                // TODO: unwrap aggregate exception...
+                try
+                {
+                    // Once the blocking call returns, the result should be available synchronously.
+                    return unaryResponseTcs.Task.Result;
+                }
+                catch (AggregateException ae)
+                {
+                    throw ExceptionHelper.UnwrapRpcException(ae);
+                }
             }
         }
 
diff --git a/src/csharp/Grpc.Core/RpcException.cs b/src/csharp/Grpc.Core/RpcException.cs
index 5a9d0039bc9129c781e207d301f857d780574675..e1cf64ca56af8a50a2bf6fbe0d2825bc654f9a4e 100644
--- a/src/csharp/Grpc.Core/RpcException.cs
+++ b/src/csharp/Grpc.Core/RpcException.cs
@@ -49,7 +49,8 @@ namespace Grpc.Core
             this.status = status;
         }
 
-        public Status Status {
+        public Status Status
+        {
             get
             {
                 return status;
diff --git a/src/csharp/Grpc.Core/ServerCallHandler.cs b/src/csharp/Grpc.Core/ServerCallHandler.cs
index 1296947f34d56569039593d2bc3d7a2aeb61652c..289f97aecee2777f6a7718bed807d1cacb3278c4 100644
--- a/src/csharp/Grpc.Core/ServerCallHandler.cs
+++ b/src/csharp/Grpc.Core/ServerCallHandler.cs
@@ -111,6 +111,8 @@ namespace Grpc.Core
 
             var finishedTask = asyncCall.ServerSideStreamingRequestCallAsync(new NullObserver<byte[]>());
 
+            // TODO: this makes the call finish before all reads can be done which causes trouble
+            // in AsyncCall.HandleReadFinished callback. Revisit this.
             asyncCall.SendStatusFromServerAsync(new Status(StatusCode.Unimplemented, "No such method.")).Wait();
 
             finishedTask.Wait();
diff --git a/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs b/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs
new file mode 100644
index 0000000000000000000000000000000000000000..18702e1cc4257c75703de7b85b9cd3aa8b5f6025
--- /dev/null
+++ b/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs
@@ -0,0 +1,57 @@
+#region Copyright notice and license
+
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+
+namespace Grpc.Core.Utils
+{
+    public static class ExceptionHelper
+    {
+        /// <summary>
+        /// If inner exceptions contain RpcException, rethrows it.
+        /// Otherwise, rethrows the original aggregate exception.
+        /// Always throws, the exception return type is here only to make the.
+        /// </summary>
+        public static Exception UnwrapRpcException(AggregateException ae) {
+            foreach (var e in ae.InnerExceptions)
+            {
+                if (e is RpcException)
+                {
+                    throw e;
+                }
+            }
+            throw ae;
+        }
+    }
+}
+