WCF host error -> "Kontrakt wymaga elementu Duplex"

0

Witam wszystkich.
Mam mały problem z moim serwisem WCF-owym. Próbuje napisać serwis z interfejsem Callback. Udało mi się już coś stworzyć, ale niestety gdy odpalam hosta wyskakuje mi błąd "Kontrakt wymaga elementu Duplex, albo element Binding „NetTcpBinding” go nie obsługuje lub jest niepoprawnie skonfigurowany do jego obsługi". Czy ktoś mógłby rzucić okiem na moje wypociny i zobaczyć co robię źle? Bo ja już przyglądam się temu kodowi od jakiego czasu i nie znajduje błędu.
Oto moje kontrakty:

  public interface IFileServiceCallback
    {
        [OperationContract(IsOneWay = true)]
        void UserEnter(User user);

        [OperationContract(IsOneWay = true)]
        void UserLeave(User user);
    }

    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IFileServiceCallback))]
    public interface IFileService
    {
        [OperationContract(IsInitiating = false, IsTerminating = false, IsOneWay = false)]
        Stream DownloadFile(StorageFileInfo _fileInfo);

        [OperationContract(IsInitiating = false, IsTerminating = false, IsOneWay = true)]
        void UploadFile(FileUploadMessage _fileUpload);

        [OperationContract(IsInitiating = false, IsTerminating = false, IsOneWay = false)]
        List<StorageFileInfo> FilesList();

        [OperationContract(IsInitiating = false, IsTerminating = false, IsOneWay = false)]
        User SelectUser(User user);

        [OperationContract(IsInitiating = false, IsTerminating = false, IsOneWay = false)]
        List<User> SelectUserAll();

        [OperationContract(IsInitiating = false, IsTerminating = false, IsOneWay = false)]
        User InsertUser(User user);

        [OperationContract(IsOneWay = false, IsInitiating = true, IsTerminating = false)]
        List<User> Join(User user);

        [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = true)]
        void Leave(User user);

    }

Serwis:

[ServiceBehavior(
        InstanceContextMode = InstanceContextMode.PerSession,
        ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class FileService : IFileService
    {
        private object lockObject = new object();
   
        public delegate void FileServiceEventHendler(object sender, FileServiceEventArg e);
        private FileServiceEventHendler myEventHandler = null;

        #endregion

        private Dictionary<User, FileServiceEventHendler> users = new Dictionary<User, FileServiceEventHendler>();
        private IFileServiceCallback callback = null;

        #region IFileService Members

        public Stream DownloadFile(StorageFileInfo _fileInfo)
        {//...        }

        public void UploadFile(FileUploadMessage _fileUpload)
        {
            //...
        }

        public List<StorageFileInfo> FilesList()
        {
           / /...
           
        }
     
        public User SelectUser(User user)
        {
            
        }

        public List<User> SelectUserAll()
        {
            
        }

        public User InsertUser(User user)
        {
            
        }


        public List<User> Join(User user)
        {
            bool userAdded = false;
            myEventHandler = new FileServiceEventHendler(MyEventHandlerFunction);
            lock (lockObject)
            {
                if (!users.Keys.ToList().Exists(o => o._Id == user._Id))
                {
                    users.Add(user, myEventHandler);
                    userAdded = true;
                }
            }

            if (!userAdded) return null;

            callback = OperationContext.Current.GetCallbackChannel<IFileServiceCallback>();
            FileServiceEventArg e = new FileServiceEventArg(user, null, MesaageType.UserEnter);
            this.broadcastMessage(e);


            return this.users.Keys.ToList();
        }

        public void Leave(User user)
        {
            
        }

        #endregion


        private void broadcastMessage(FileServiceEventArg e)
        {
            if (users == null) return;

            foreach (FileServiceEventHendler handler in this.users.Values)
            {
                handler.BeginInvoke(this, e, new AsyncCallback(EndAsync), null); 
            }
        }

        private void EndAsync(IAsyncResult e)
        {
            FileServiceEventHendler d = null;
            try
            {
                d = (FileServiceEventHendler)((AsyncResult)e).AsyncDelegate;
                d.EndInvoke(e);
            }
            catch
            { }
        }

        private void MyEventHandlerFunction(object sender, FileServiceEventArg e)
        {
            try
            {
                switch (e._MessageType)
                {
                    case MesaageType.UserEnter:
                        callback.UserEnter(e._FromUser);
                        break;
                    case MesaageType.UserLeave:
                        callback.UserLeave(e._FromUser);
                        break;
                }
            }
            catch
            {
                //Tutaj powinno znaleść się wyrzucenie użytkownika z głównej listy
            }
        }
    }
 

Wyrzuciłem mało ważny kod z ciał metod aby zmniejszyć ilość kodu
Host:

 
class Program
    {
        static ServiceHost host = null;
        static FileService service = null;

        static void Main(string[] args)
        {
            service = new FileService();
            service._InfoActionEvent += new EventHandler<ActionInfoArg>(service__InfoActionEvent);

            host = new ServiceHost(service);
            //host = new ServiceHost(typeof(FileService), new Uri("net.tcp://localhost:7000/FileService")); 
            host.Faulted += new EventHandler(host_Faulted);

            try
            {
                host.Open();
                Console.WriteLine("Host started\n");
                Console.WriteLine("If you wont exit press Enter");
                Console.ReadLine();
            }

            catch (Exception exp)
            { 
            }
        }

        static void host_Faulted(object sender, EventArgs e)
        {
            Console.WriteLine("Host faulted");
        }

        static void service__InfoActionEvent(object sender, ActionInfoArg e)
        {
            Console.WriteLine(e._ActionName + "\n");
        }

       
    }

App.config hosta:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    
    
    <services>
      <service name="FileServer.Services.FileService" behaviorConfiguration="MyBehavior">
        <endpoint 
          binding="netTcpBinding"
					address="net.tcp://localhost:7000/FileService"
					contract="FileServer.Services.IFileService"
					bindingConfiguration="DuplexBinding" />
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior  name="MyBehavior">
          <serviceThrottling maxConcurrentSessions="10000" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    
    <bindings>
      <netTcpBinding>
        <binding name="DuplexBinding" sendTimeout="00:01:00" transferMode="Streamed" maxReceivedMessageSize="20480000" >
          <reliableSession enabled="true" />
          <security mode="None" />
        </binding>
      </netTcpBinding>
    </bindings>
    
    
  </system.serviceModel>
</configuration>
 

Za wszelkie uwagi i pomoc z góry dzięki wielkie

0

Udało mi się w końcu odszukać błąd jaki popełniłem:P. Jak zwykle to bywa w moim przypadku to był szkolny błąd:P. W app.config TransferMode nie można ustawiać jeśli wykorzystuje się DuplexBinding:P

1 użytkowników online, w tym zalogowanych: 0, gości: 1