I want to create a proxy class that supports asynchronous operations against a REST-based service.
For the sake of discussion, let's say I have a service, IService
:
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet(UriTemplate = "{a}/{b}")]
void Action(string a, string b);
}
I am able to easily create a synchronous proxy class with:
class Client: ClientBase<IService>, IService
{
public void Action(string a, string b)
{
Channel.Action(a, b);
}
}
(this technique is from this article)
Is there a similarly straightforward way to make the proxy support asynchronous operations (either the BeginAction
/EndAction
or ActionAsync
patterns)? Or is the best practice to roll my own manually?
Note that I am unable to add a Service Reference in Visual Studio because there is no metadata available.
If you replace the operation contract with a corresponding Begin/End pair, it should work for REST-based contracts as well. You can even have both sync and async versions of the operation on the client (but in this case you need to have the [WebGet] attribute on the synchronous version only).
public class StackOverflow_6846215
{
[ServiceContract(Name = "ITest")]
public interface ITest
{
[OperationContract]
[WebGet]
int Add(int x, int y);
}
[ServiceContract(Name = "ITest")]
public interface ITestClient
{
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object state);
int EndAdd(IAsyncResult asyncResult);
[OperationContract]
[WebGet]
int Add(int x, int y);
}
public class Client : ClientBase<ITestClient>, ITestClient
{
public Client(string baseAddress)
:base(new WebHttpBinding(), new EndpointAddress(baseAddress))
{
this.Endpoint.Behaviors.Add(new WebHttpBehavior());
}
public IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object state)
{
return this.Channel.BeginAdd(x, y, callback, state);
}
public int EndAdd(IAsyncResult asyncResult)
{
return this.Channel.EndAdd(asyncResult);
}
public int Add(int x, int y)
{
return this.Channel.Add(x, y);
}
}
public class Service : ITest
{
public int Add(int x, int y)
{
return x + y;
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
host.Open();
Console.WriteLine("Host opened");
Client client = new Client(baseAddress);
Console.WriteLine("Sync result: {0}", client.Add(66, 77));
client.BeginAdd(44, 55, delegate(IAsyncResult ar)
{
int result = client.EndAdd(ar);
Console.WriteLine("Async result: {0}", result);
}, null);
Console.WriteLine("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}