views:

148

answers:

4

In my solution there's a few WCF services, each of them implementing it's own callback interface. Let's say they are called: Subscribe1, with ISubscribe1 and ICallback1, etc.

It happens there are a few methods shared among ICallbacks, so I made a following interface:

interface ICallback
{
    [OperationContract]
    void CommonlyUsedMethod();
}

and i inherited it in all: ICallback1 : ICallback, ICallback2 : ICallback, etc. And deleted the CommonlyUsedMethod() from all callback interfaces.

Now, on the service-side code, everything compiles fine and services can start working as usual. But, when I updated the service references for the client, CommonlyUsedMethod() dissapeared from the reference.cs file (the ISubscribeCallback part), and could no longer be used to send data to back to the client.

+3  A: 

try to set the ServiceContract attribute on the base interface also.

AZ
I'm almost positive that this is what is going wrong. Will double check shortly. I have this exact scenario in my app at work, and it's working great there.
Andrew Anderson
I already had that in my regular callback interfaces; this is pretty much exactly how they look like: [ServiceContract] interface ICallback1 : ICallback { [OperationContract] Method1(); [OperationContract] Method2(); ... } ... now that you said, I tried adding [ServiceContract] to the ICallback as well, but it did not help :( also, tried removing servicecontract (and other combinations)
avance70
A: 

Does this reflect what you have in your code?

[ServiceContract]
public interface ICallbackBase
{
    [OperationContract]
    void CommonlyUsedMethod();
}

[ServiceContract]
public interface ICallback1 : ICallbackBase
{
    [OperationContract]
    void SpecificMethod();
}

This is essentially the structure I have in my production solution, and then I use the proxies that are generated when I add a Service Reference to access my methods from the client.

For reference, the generated interface then looks like this:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="MyNamespace.ICallback1")]
public interface ICallback1 {

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ICallbackBase/CommonlyUsedMethod", ReplyAction="http://tempuri.org/ICallbackBase/CommonlyUsedMethodResponse")]
    void CommonlyUsedMethod();

}

Note the "ICallbackBase" in the OperationContractAttribute - it really does know where the method came from.

Andrew Anderson
yes, that's my code as well, but in the reference, there's only "SpecificMethod()" and no "CommonlyUsedMethod()" ... i will start a new clean solution now, just in case i missed something, and report back the results.
avance70
A: 

Ok, this is the exact code, I condensed it as much as I can. Just start a new console application and copy/paste it. Start it and add a service reference to it. CommonlyUsedMethod() is not present in the reference, while the other methods are. Could it be framework 4?

using System;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace TestService
{
    class Program
    {
        static void Main()
        {
            var serviceHost=new ServiceHost(typeof(Subscribe1), new Uri("net.tcp://localhost:8888"));
            serviceHost.Description.Behaviors.Add(new ServiceMetadataBehavior());
            serviceHost.AddServiceEndpoint(typeof(ISubscribe1), new NetTcpBinding(SecurityMode.None), string.Empty);
            serviceHost.AddServiceEndpoint("IMetadataExchange", MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
            serviceHost.Open();

            Console.WriteLine("Working!");
            while(Console.ReadKey(true).Key!=ConsoleKey.Escape) { }
        }
    }

    [ServiceContract]
    interface ICallbackBase
    {
        [OperationContract]
        void CommonlyUsedMethod();
    }

    [ServiceContract]
    interface ICallback1 : ICallbackBase
    {
        [OperationContract]
        void SpecificMethod();
    }

    [ServiceContract(CallbackContract=typeof(ICallback1))]
    interface ISubscribe1
    {
        [OperationContract]
        void TestMethod();
    }

    [ServiceBehavior]
    class Subscribe1 : ISubscribe1
    {
        [OperationBehavior]
        public void TestMethod()
        {
        }
    }
}
avance70
Here's the solution: http://social.msdn.microsoft.com/Forums/en/wcf/thread/ef896836-dec1-4fa6-9956-e3a4958643ce ... essentially: add (to the above code) an empty interface ISubscribeBase which has the ICallbackBase callback and is inherited by ISubscribe1.
avance70
also: [ServiceContract] aren't really required anywhere in this case
avance70
A: 

I'm not sure that what you are trying to do using WCF is possible. When you use inheritance in WCF you need to apply the KnownType attribute to the DataContract so that the DataContractSerializer will know to serialize it and make it available on the other end. Since you cannot put the KnownType attribute on interfaces, there is no way to tell the serializer that this is needed on the other end. Thus is does not show up when you implement it on the client.

CkH