简体   繁体   中英

How to consume REST-based services asynchronously with WCF?

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();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM