8

I am using WCF Async calls in my project and i am using Client side asynchronous methods. I have a scenario like below -

  //Code in Business Layer and this method is called from Web layer 
    private void GetGeneralNews()
    {
        client.BeginGetGeneralNewsFeed(GeneralNewsCallback, null);
    }

    //Call Back Method
    private static void GeneralNewsCallback(IAsyncResult asyncResult)
    {
       string response = string.Empty;

       try
       {
          response = client.EndGetGeneralNewsFeed(asyncResult);
       }
       catch(Exception ex)
       {
          throw ex; // Here is the problem. It does not throw the exception to the web layer instead it will suppress the   error.
       }
    }

So as shown in the above code snippet it does not throw the exception from business layer to web layer as it will be suppressed here in business layer itself.

I checked in some of the blogs and sites they are suggesting to go for async and await approach, as i have .NET 4.0 framework and i am seeing "Generate task-based Operations" option disabled. So if there are any options using "IAsyncResult" (Begin & End in client side) please let me know. If there are any other approaches also welcome.

Kindly someone help me.

Thanks.

Abhijith Nayak
  • 448
  • 7
  • 21
  • check the link might be helpful http://blogs.msdn.com/b/nikos/archive/2011/03/14/how-to-implement-iasyncresult-in-another-way.aspx#comments – reapen Apr 07 '15 at 14:42
  • Are you saying that your `catch` block does not catch any exception at all? If an unhandled exception is thrown in the server side code, your `catch` block above should catch a `FaultException` by default. – Gary Wright Apr 13 '15 at 08:30
  • So you want an exception to bubble up to the caller when he calls `GetGeneralNews`? – usr Apr 13 '15 at 10:32
  • On the same line as @usr, what do you expect to see on the client side? Do you want a SOAP fault, do you want an errors collection? Do you want a .NET Exception? – Joshua Drake Apr 15 '15 at 19:26
  • Also, can you include the contract of the service that provides the BeginGetGeneralNewsFeed? – Joshua Drake Apr 15 '15 at 21:04
  • How is your client calling a private method? – Joshua Drake Apr 16 '15 at 13:56

3 Answers3

2

Here is a sample app which shows that WCF doesn't swallow the exception. If you don't receive the exception, it must be swallowed by your server side code.

using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using WcfQ.QServiceReference;

namespace WcfQ
{
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class QService : IQService
{
    public void Foo()
    {
        throw new ApplicationException("Please catch this");
    }
}

[ServiceContract]
public interface IQService
{
    [OperationContract]
    void Foo();
}

class Program
{
    static private QServiceClient client;

    static void Main(string[] args)
    {
        ServiceHost host = new ServiceHost(typeof(QService), new Uri("http://localhost:20001/q"));
        AddWsdlSupport(host);
        host.AddServiceEndpoint(typeof (IQService), new WSHttpBinding(SecurityMode.None), "");
        host.Open();

        client = new QServiceClient();
        client.BeginFoo(FooCallback, null);
        Console.WriteLine("ready");
        Console.ReadKey();
    }

    private static void FooCallback(IAsyncResult asyncResult)
    {
        try
        {
            client.EndFoo(asyncResult);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Got the exception: " + ex.Message);
        }
    }

    static void AddWsdlSupport(ServiceHost svcHost)
    {
        ServiceMetadataBehavior smb = svcHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
        // If not, add one
        if (smb == null)
            smb = new ServiceMetadataBehavior();
        smb.HttpGetEnabled = true;
        smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
        svcHost.Description.Behaviors.Add(smb);
        // Add MEX endpoint
        svcHost.AddServiceEndpoint(
          ServiceMetadataBehavior.MexContractName,
          MetadataExchangeBindings.CreateMexHttpBinding(),
          "mex"
        );

    }
}

}

Here is the output of this program:

ready 
Got the exception: Please catch this
Alon Catz
  • 2,417
  • 1
  • 19
  • 23
0

1) If you have already generated WCF client code with async ("Begin..."/"End...") methods - than you can use TPL's task API to work with WCF (ContinueWith etc.) via Task.Factory.FromAsync (example) - good for dealing with legacy IAsyncResult ("Begin..."/"End...") methods/APIs (simple though, you can see source with reflector);

2) Tool-generated client code is not good approach - instead you can write your own universal client-proxy with true-async support (not just using background thread). Here is good example how to start, you need wrap "Begin..."/"End..." methods with task based methods (use same Task.Factory.FromAsync) and use expression trees to get rid string based service method calls (I can't share my class source).

Or you can use existing solutions like this.

3) Don't forget about ConfigureAwait.

Edit:

You don't have to generate task-based operations, it's enough to generate WCF client code with async service operation methods ("Begin..."/"End..."). Or you can even have only synchronous WCF contract! (see links). TPL available in .NET 4 (without async/await syntactic sugar - which is CSharp 5.0 language feature). Use it (ContinueWith instead await + WhenAny, WhenAll). I used it even in 3.5 via Microsoft Reactive Extensions v1.0.2856.0. AFAIK Reactive Extensions was the initial version which than was included in BCL. ParallelExtensionsExtras may be useful as well

Community
  • 1
  • 1
SalientBrain
  • 2,431
  • 16
  • 18
0

Anyway i solved this by using TPL (Task Parallel Library).

Reason i was getting problems in the above approach is my new threads will not be able to recognize the main thread, from which layer the method has been called. So using TPL i made my main thread wait till my other threads do the job and come back and then based on the response throw the exception.

Hope it helps.

Abhijith Nayak
  • 448
  • 7
  • 21