2
votes

I have created WCF service in VS2015:

[ServiceContract(CallbackContract = typeof(IMyCallback))]
public interface IMyService { }

IMyCallback looks like:

[ServiceContract]
public interface IMyCallback {

[OperationContract]
Task<string> OnServerEvent(UserAppEventData evData);

I've built the server, run it, then added service reference (by right click on solution explorer).
The client object is defined as

 [CallbackBehaviorAttribute(
     ConcurrencyMode = ConcurrencyMode.Reentrant,
     IncludeExceptionDetailInFaults = true,
     UseSynchronizationContext = true,
     ValidateMustUnderstand = true
)]
public class QMyClient : IMyCallback { }

Automatically generated interface implementation made method in sync manner:

public string OnServerEvent(UserAppEventData evData) { }

This code does't work (and isn't asynchronous) and hangs client at OnServerEvent.

When I changed code manuallly to

public async Task<string> OnServerEvent(UserAppEventData evData)

and have done the same in auto generated "service references\...\Reference.cs, all works fine. But I don't want to change Referenece.cs every time I'm updating Service Reference.

Is there any method to force "Update Service Reference" make TBA OperationContractAttribute on callback?

At ordinary WCF service direction everything works OK, VS generates task based operations.

2
You can avoid using "add service reference" in VS. Add the reference of the service assembly where ServiceContract is defined. Create a client proxy class that will extend ClientBase<IMyService> class. Next you can call await OnServerEvent(). Hope it makes sense. - Yawar Murtaza

2 Answers

2
votes

By default the service reference you've added to solution doesn't have asynchronous operations, but you can enable them and decide which option you use for your async methods - task-based or old-fashion asynchronous. This option is available in Advanced settings for service reference.

enter image description here

If you're using a svcutil tool, it will create the task-based methods by default, however, you can change that behavior by some flags like /async or /syncOnly.

1
votes

What @VMAtm suggested will work out just fine.

I think, you could also use ChannelFactory for this scenario. It is very flexible and you can then await on the service operations from client side. Additional benefit, you don't need to modify client when there are these kind of changes on service side.

Something like:

var channelFactory = new ChannelFactory<IService>(
                    "WSHttpBinding_IService" // endpoint name
                    ); 

IService channel = channelFactory.CreateChannel();

string result = await channel.OnServerEvent();

Console.WriteLine(result);

Please note that for this scenario, you will have to import common interface library to client side as dll because then it will need to know about contracts and data contracts.