Inheritance problem?

I'm having a problem creating a ServiceHost using two servicecontracts which inherit from the same parent servicecontract. When I try to create the host the following error occurs: ArgumentException: An item with the same key has already been added. My guess is that the creation thinks that both IServiceContract's are two different contracts, which they are not. Is there any solution to this or something I do wrong Creating one contract for both contracts is no option (duo to more inheritance).

Call to create the serviceHost:
Uri uri = new Uri("net.tcp://localhost:8100/LocationService");
ServiceHost PostalCodeHost = new ServiceHost(typeof(PostalCodeService), uri);
< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Class declaration:
 
public class PostalCodeService : IGetDutchAddressServiceContract, IGetDutchVersionServiceContract

Contracts:
using
System.ServiceModel;
using Prodigy.WorkPool;

namespace Prodigy.PostalCode

{
   
[ServiceContract(

    Name = "GetDutchVersionServiceContract",

    Session = true,

    Namespace = "Prodigy.PostalCode",

    CallbackContract = typeof(ICallbackGetDutchVersionServiceContract))]

    public interface IGetDutchVersionServiceContract : Prodigy.WorkPool.IServiceContract

    {

       [OperationContract(Name = "GetDutchVersion", IsOneWay = true)]

       void GetDutchVersion(GetDutchVersionQuestionJobMessage message);

    }

 

    [ServiceContract(

     Name = "ICallbackGetDutchVersionServiceContract",

     Session = true,

     Namespace = "Prodigy.PostalCode")]

    public interface ICallbackGetDutchVersionServiceContract : Prodigy.WorkPool.ICallbackServiceContract

    {

       [OperationContract(Name = "CallbackGetDutchVersion", IsOneWay = true)]

       void CallbackGetDutchVersion(GetDutchVersionReplyJobMessage message);

    }

}

 

using System.ServiceModel;

using Prodigy.WorkPool;

 

namespace Prodigy.PostalCode

{

   [ServiceContract(

    Name = "GetDutchAddressServiceContract",

    Session = true,

    Namespace = "Prodigy.PostalCode",

    CallbackContract = typeof(ICallbackGetDutchAddressServiceContract))]

   public interface IGetDutchAddressServiceContract : Prodigy.WorkPool.IServiceContract

   {

      [OperationContract(Name = "GetDutchAddress", IsOneWay = true)]

      void GetDutchAddress(GetDutchAddressQuestionJobMessage message);

   }

 

    [ServiceContract(

     Name = "ICallbackGetDutchAddressServiceContract",

     Session = true,

     Namespace = "Prodigy.PostalCode")]

    public interface ICallbackGetDutchAddressServiceContract : Prodigy.WorkPool.ICallbackServiceContract

    {

      [OperationContract(Name = "CallbackGetDutchAddress", IsOneWay = true)]

      void CallbackGetDutchAddress(GetDutchAddressReplyJobMessage message);

    }

}

Greets,
Ivo



Answer this question

Inheritance problem?

  • nicope

    Greetings --

    Sorry for the delayed reply. I have tried to reproduce the problem on current WCF builds, but I have failed. As such, I'm hopeful that this has been fixed.

    I constructed a repro from the above code. It is below.

    using System;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    
    namespace Prodigy.WorkPool
    {
      [ServiceContract(Name = "ServiceContract", Namespace = "Prodigy.WorkPool", Session = true, CallbackContract = typeof(ICallbackServiceContract))]
      public interface IServiceContract
      {
        [OperationContract]
        void NoopMethod();
      }
    
      [ServiceContract(Name = "CallbackServiceContract", Session = true, Namespace = "Prodigy.WorkPool")]
      public interface ICallbackServiceContract
      {
        [OperationContract(Name = "ServiceException", IsOneWay = true)]
        void ServiceException(Exception serviceException, string senderSessionId, int senderSeqNr);
      }
    }
    
    namespace Prodigy.PostalCode
    {
      [ServiceContract(Name = "GetDutchVersionServiceContract", Session = true, Namespace = "Prodigy.PostalCode", CallbackContract = typeof(ICallbackGetDutchVersionServiceContract))]
      public interface IGetDutchVersionServiceContract : Prodigy.WorkPool.IServiceContract
      {
        [OperationContract(Name = "GetDutchVersion", IsOneWay = true)]
        void GetDutchVersion(GetDutchVersionQuestionJobMessage message);
      }
    
      public interface ICallbackGetDutchVersionServiceContract : Prodigy.WorkPool.ICallbackServiceContract
      {
        [OperationContract(Name = "CallbackGetDutchVersion", IsOneWay = true)]
        void CallbackGetDutchVersion(GetDutchVersionReplyJobMessage message);
      }
    
      [ServiceContract(Name = "GetDutchAddressServiceContract", Session = true, Namespace = "Prodigy.PostalCode", CallbackContract = typeof(ICallbackGetDutchAddressServiceContract))]
      public interface IGetDutchAddressServiceContract /*: Prodigy.WorkPool.IServiceContract*/
      {
        [OperationContract(Name = "GetDutchAddress", IsOneWay = true)]
        void GetDutchAddress(GetDutchAddressQuestionJobMessage message);
      }
    
      public interface ICallbackGetDutchAddressServiceContract : Prodigy.WorkPool.ICallbackServiceContract
      {
        [OperationContract(Name = "CallbackGetDutchAddress", IsOneWay = true)]
        void CallbackGetDutchAddress(GetDutchAddressReplyJobMessage message);
      }
    
      public class PostalCodeService : IGetDutchAddressServiceContract, IGetDutchVersionServiceContract
      {
        public void GetDutchVersion(GetDutchVersionQuestionJobMessage message)
        {
          return;
        }
    
        public void GetDutchAddress(GetDutchAddressQuestionJobMessage message)
        {
          return;
        }
    
        public void NoopMethod()
        {
          return;
        }
      }
    
      [DataContract]
      public class GetDutchVersionQuestionJobMessage { }
    
      [DataContract]
      public class GetDutchVersionReplyJobMessage { }
    
      [DataContract]
      public class GetDutchAddressQuestionJobMessage { }
    
      [DataContract]
      public class GetDutchAddressReplyJobMessage { }
    
      public class Program
      {
        public static void Main(string[] args)
        {
          Uri uri = new Uri("net.tcp://localhost:8100/LocationService");
          ServiceHost PostalCodeHost = new ServiceHost(typeof(PostalCodeService), uri);
          PostalCodeHost.AddServiceEndpoint("Prodigy.PostalCode.IGetDutchAddressServiceContract", new NetTcpBinding(), "address");
          PostalCodeHost.AddServiceEndpoint("Prodigy.PostalCode.IGetDutchVersionServiceContract", new NetTcpBinding(), "version");
          PostalCodeHost.Open();
    
          Console.WriteLine("Service Started");
          Console.ReadLine();
        }
      }
    }
    

    I made a few changes -- some to make the code compile and some to remove extraneous info.

    First, I added a method to the base IServiceContract as we don't allow empty service contracts to be specified.

    Second, I added empty implementations of the messages.

    Third, I removed the [ServiceContract] attributes from callback contracts as they are not necessary (in fact, they are ignored).

    Lastly, I changed the AddServiceEndpoint(...) code to take a name instead of a type. Earlier CTPs will expect a type here (this is a recent change).

    If you can still repro this on current bits, please let me know.

    Thanks,

    -mike


  • Alan Faux

    Ivo --

    Thanks for raising the question. Looking at the code, I don't see any errors. Could you post both IServiceContract and ICallbackServiceContract

    By the way, you should be aware that [ServiceContract] tags are unnecessary on the CallbackContract. In this scenario, they will be ignored.

    Cheers,
    -mike

  • Radexx

    First of all thanks for the quick reply. I have added the code of both contracts below. I also tried rewriting the JobSessionId in the callbackcontract to an int, this didn't help anything though (JobSessionId is a datacontact with a few datamembers of normal types (int, string etc.).

    using
    System;< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

    using System.ServiceModel;

    using System.Runtime.Serialization;

     

    namespace Prodigy.WorkPool

    {

      [ServiceContract(

       Name = "ServiceContract",

       Namespace = "Prodigy.WorkPool",

       Session = true,

       CallbackContract = typeof(ICallbackServiceContract))]

      public interface IServiceContract

      {

      }

     

      [ServiceContract(

       Name = "CallbackServiceContract",

       Session = true,

       Namespace = "Prodigy.WorkPool")]

      public interface ICallbackServiceContract

      {

        [OperationContract(Name = "ServiceException", IsOneWay = true)]

        [KnownType(typeof(System.ArgumentException))]

        [KnownType(typeof(System.ArgumentNullException))]

        void ServiceException(Exception serviceException, JobSessionId senderSessionId, int senderSeqNr);

      }

    }


  • greenie

    Added findings: It seems to workf if I leave out the [OperationContract] in the callback. This means that you can only define a parent contract without OperationContract attribute's (which is kinda pointless). Is this a bug or intended

    Ivo Klerkx


  • Inheritance problem?