سؤال

I am trying to create a WCF service, that has a webHttpBinding endpoint (for Java clients) and a netTcpBinding endpoint (for .NET clients).

With the netTcpBinding endpoint I would like to be able to use callbacks in order to be alerted to events, but when I try to configure this, WCF complains because the service also has the webHttpBinding endpoint, which doesn't support callbacks.

Is there a way of having the callback utilised by one endpoint but not another?

هل كانت مفيدة؟

المحلول

No, the binding will validate that it can honor the contract; if the contract is a duplex contract (i.e., it specifies a CallbackContract) but the binding can't do duplex, then it will throw during validation.

What you can do is to have a base contract which is used by the webHttpBinding endpoint, and another contract (this time a duplex one), derived from the first, which is used by the netTcpBinding endpoint.

The code below shows an example of such contract arrangement.

public class StackOverflow_7341463
{
    [ServiceContract]
    public interface ICalc
    {
        [OperationContract, WebGet]
        int Add(int x, int y);
        [OperationContract, WebGet]
        int Subtract(int x, int y);
        [OperationContract, WebGet]
        int Multiply(int x, int y);
        [OperationContract, WebGet]
        int Divide(int x, int y);
    }
    [ServiceContract(CallbackContract = typeof(ICalcNotifications))]
    public interface INotifyingCalc : ICalc
    {
        [OperationContract]
        void Connect();
        [OperationContract]
        void Disconnect();
    }
    [ServiceContract]
    public interface ICalcNotifications
    {
        [OperationContract(IsOneWay = true)]
        void OperationPerformed(string text);
    }
    public class Service : INotifyingCalc
    {
        static List<ICalcNotifications> clients = new List<ICalcNotifications>();

        #region ICalc Members

        public int Add(int x, int y)
        {
            this.NotifyOperation("Add", x, y);
            return x + y;
        }

        public int Subtract(int x, int y)
        {
            this.NotifyOperation("Subtract", x, y);
            return x - y;
        }

        public int Multiply(int x, int y)
        {
            this.NotifyOperation("Multiply", x, y);
            return x * y;
        }

        public int Divide(int x, int y)
        {
            this.NotifyOperation("Divide", x, y);
            return x / y;
        }

        #endregion

        #region INotifyingCalc Members

        public void Connect()
        {
            var callback = OperationContext.Current.GetCallbackChannel<ICalcNotifications>();
            clients.Add(callback);
        }

        public void Disconnect()
        {
            var callback = OperationContext.Current.GetCallbackChannel<ICalcNotifications>();
            clients.Remove(callback);
        }

        #endregion

        private void NotifyOperation(string operationName, int x, int y)
        {
            foreach (var client in clients)
            {
                client.OperationPerformed(string.Format("{0}({1}, {2})", operationName, x, y));
            }
        }
    }
    class MyCallback : ICalcNotifications
    {
        public void OperationPerformed(string text)
        {
            Console.WriteLine("Operation performed: {0}", text);
        }
    }
    public static void Test()
    {
        string baseAddressTcp = "net.tcp://" + Environment.MachineName + ":8008/Service";
        string baseAddressHttp = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddressHttp), new Uri(baseAddressTcp));
        host.AddServiceEndpoint(typeof(ICalc), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
        host.AddServiceEndpoint(typeof(INotifyingCalc), new NetTcpBinding(SecurityMode.None), "");
        host.Open();
        Console.WriteLine("Host opened");

        var factory = new DuplexChannelFactory<INotifyingCalc>(
            new InstanceContext(new MyCallback()),
            new NetTcpBinding(SecurityMode.None),
            new EndpointAddress(baseAddressTcp));
        var proxy = factory.CreateChannel();
        proxy.Connect();
        Console.WriteLine("Proxy connected");

        Console.WriteLine(new WebClient().DownloadString(baseAddressHttp + "/Add?x=4&y=7"));
        Console.WriteLine(new WebClient().DownloadString(baseAddressHttp + "/Multiply?x=44&y=57"));
        Console.WriteLine(new WebClient().DownloadString(baseAddressHttp + "/Divide?x=432&y=16"));

        proxy.Disconnect();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();

        ((IClientChannel)proxy).Close();
        factory.Close();
        host.Close();
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top