Given this interface
[ServiceContract]
public interface IProductService
{
[OperationContract]
Product Get(int id);
}
I would like to manually (that is, without using scvutil or Add Service Reference in VS) create a client-side proxy.
I do it in the following way
public class ProductService: IProductService
{
readonly ChannelFactory<IProductService> factory;
public ProductService()
{
factory = new ChannelFactory<IProductService>("*");
}
public Product Get(int id)
{
var channel = factory.CreateChannel();
return channel.Get(id);
}
}
My problem is that I also want async/await version of this method, only on client-side, server side is still synchronous.
I want this to be a generic solution because I have many methods and services of this sort.
If you're using ChannelFactory
to allow for async-await your interface needs to return a Task
or Task<T>
.
It will force your server side to also return a task but you can do that synchronously with Task.CompletedTask
and Task.FromResult
if you insist on keeping it synchronous (though why would you if you have the option).
For example:
[ServiceContract]
interface IProductService
{
[OperationContract]
Task<Product> GetAsync(int id);
}
class ProductService : IProductService
{
ChannelFactory<IProductService> factory;
public ProductService()
{
factory = new ChannelFactory<IProductService>("*");
}
public Task<Product> GetAsync(int id)
{
var channel = factory.CreateChannel();
return channel.GetAsync(id);
}
}
class ProductAPI : IProductService
{
public Task<Product> GetAsync(int id) => Task.FromResult(Get(id))
}
You can actually do that without changing the service itself. You can simply define a second interface which contains async and Task
returning versions of the methods and is marked with [ServiceContract(Name = "NameOfTheIterfaceWhichIsActuallyExposedOnTheServer")]
In the example you mentioned you would define a second interface with GetAsync()
operation:
[ServiceContract(Name = "IProductService")]
public interface IProductServiceAsync
{
[OperationContract]
Task<Product> GetAsync(int id);
}
and even though your service still implements and exposes IProductService
you can use ChannelFactory<IProductServiceAsync>
to call into it. As long as the method names match the GetFoo
/GetFooAsync
pattern everything will just work. That's how Add Service Reference in Visual Studio can generate you an async service reference to a synchronous service.
See Calling a synchronous WCF method asynchronously using ChannelFactory for a more detailed explanation on how this work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With