none
Не могу разобраться с callback в wcf RRS feed

  • Вопрос

  • Доброе время суток. Только начинаю разбираться с технологией WCF. Пытаюсь создать self-hosted приложение, которое возвращает данные клиенту через callback функцию. Пока использую шаблонный контракт (VisualStudio 2010, C#)

    Сервис размещаю в консольном приложении (InstanceContextMode выставлен в PerSession, использую nettcpbinding) :

     

    ServiceHost host = new ServiceHost(typeof(Service1));
    
    host.Open();
    
    Console.WriteLine("runing...");
    
    Console.ReadLine();
    
    host.Close();
    

    Конфиг сервиса:

    <system.serviceModel>
      <bindings>
       <netTcpBinding>
        <binding name="NewBinding0" portSharingEnabled="true" />
       </netTcpBinding>
      </bindings>
      <services>
       <service name="WcfServiceLibrary1.Service1">
        <clear />
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"
         listenUriMode="Explicit" />
        <endpoint binding="netTcpBinding" bindingConfiguration="" contract="WcfServiceLibrary1.IService1" />
        <host>
         <baseAddresses>
          <add baseAddress="net.tcp://127.0.0.1:8733/Service1" />
         </baseAddresses>
        </host>
       </service>
      </services>
      <behaviors>
       <serviceBehaviors>
        <behavior>
         <serviceMetadata />
         <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
       </serviceBehaviors>
      </behaviors>
     </system.serviceModel>
    

    Клиентское приложение - приложение WinForms с одним TextBox, Label, и Button:

    using System.ServiceModel;
    using WcfServiceLibrary1;
    
    namespace WindowsFormsApplication1
    {
      public partial class Form1 : Form
      {
    
        public Form1()
        {
          InitializeComponent();
        }
    
        private ServiceReference1.Service1Client client;
        private InstanceContext inst;
    
        
        private void button1_Click(object sender, EventArgs e)
        {
          
          client.GetData(textBox1.Text);
          
        }
    
        private void Form1_Shown(object sender, EventArgs e)
        {
          calback calb = new calback();
          calb.clientnotified += calb_clientnotified;
    
          inst = new InstanceContext(calb);
          client = new ServiceReference1.Service1Client(inst);
        }
    
        private void calb_clientnotified(object sender, clientnotifiedeventargs e)
        {
          MessageBox.Show("reply:" + e.Mesage);
        }
      }
    }
    
    
    public class calback : Icallbackint
    {
      public event clientnotifiedeventhandler clientnotified;
      public void showsrvdig(string msg)
      {
        if (clientnotified != null)
        {
          clientnotified(this, new clientnotifiedeventargs(msg));
        }
      }
    
      
    }
    
    public delegate void clientnotifiedeventhandler(object sender, clientnotifiedeventargs e);
    
    public class clientnotifiedeventargs : EventArgs
    {
      private readonly string message;
    
      public clientnotifiedeventargs(string message)
      {
        this.message = message;
      }
      public string Mesage { get { return message; } }
    }
    

    Конфиг клиента:

    <system.serviceModel>
        <bindings>
          <netTcpContextBinding>
            <binding name="NetTcpContextBinding_IService1" closeTimeout="00:01:00"
              openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
              transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
              hostNameComparisonMode="StrongWildcard" listenBacklog="10"
              maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
              maxReceivedMessageSize="65536" contextProtectionLevel="Sign">
              <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                maxBytesPerRead="4096" maxNameTableCharCount="16384" />
              <reliableSession ordered="true" inactivityTimeout="00:10:00"
                enabled="false" />
            </binding>
          </netTcpContextBinding>
        </bindings>
        <client>
          <endpoint address="net.tcp://127.0.0.1:8733/Service1" binding="netTcpContextBinding"
            bindingConfiguration="NetTcpContextBinding_IService1" contract="ServiceReference1.IService1"
            name="NetTcpContextBinding_IService1">
          </endpoint>
        </client>
      </system.serviceModel>
    

    Компиляция проходит нормально. Когда пытаюсь вызвать метод сервиса GetData получаю исключение:
    "InstanceContext, предоставленный в ChannelFactory, содержит UserObject, который не реализует CallbackContractType"

    Подскажите, что у меня не так и как бороться с подобными исключениями.

    15 октября 2010 г. 23:55

Ответы

  • Воспользуйся допечаткой или просмотри все классы в ServiceReference1. Найди среди них нужный интерфейс. Студия переименовывает его на клиентской стороне. Скорее всего он называется IService1Callback.
     
    Подчеркивает красным - это не ошибка. Ошибка - это то, что пишется в окне Errors при попытке компиляции. :)
    • Помечено в качестве ответа SiberianWolf 16 октября 2010 г. 18:25
    16 октября 2010 г. 17:25

Все ответы

  • icallbackint - это интерфейс коллбека, насколько я понял?
     
    Из кода не совсем понятно, какой именно интерфейс реализован. Убедись что это ServiceReference1.icallbackint, а не какой-нибудь WcfServiceLibrary1.icallbackint.
     
    Кстати, в английском варианте исключения указывается еще и конкретный тип нереализованного контракта.
    16 октября 2010 г. 9:39
  • Скорее всего реализую WcfServiceLibrary1.icallbackint. Как в таком случае указать, чтобы именно ServiceReference1.icallbackint реализовывался?

    Если пишу: public class calback : ServiceReference1.Icallbackint , то VS ругается на ServiceReference1

    16 октября 2010 г. 15:21
  • Если у контракта на сервисной стороне был прописан CallbackContract=typeof(icallbackint), то студия должна была сгенерировать соответствующий контракт на клиенте, при добавлении Service Reference, в неймспейсе ServiceReference1 в твоем примере.
     
    Как именно ругается на ServiceReference1? не находит в нем icallbackint? Что-нибудь похожее по имени на icallbackint есть в этом неймспейсе?
     
    16 октября 2010 г. 15:54
  • Описание сервиса:
    ServiceContract(CallbackContract = typeof(Icallbackint), SessionMode = SessionMode.Required)]
        public interface IService1

    Если класс колбэка описываю:
    public class calback : ServiceReference1.Icallbackint
    {
      public event clientnotifiedeventhandler clientnotified;
      public void showsrvdig(string msg)
      {
        if (clientnotified != null)
        {
          clientnotified(this, new clientnotifiedeventargs(msg));
        }
      } 
    }
    
    объявление класса подчеркивается красным.
    Ссылку на службу добавляю через ServiceReference
    16 октября 2010 г. 16:41
  • Воспользуйся допечаткой или просмотри все классы в ServiceReference1. Найди среди них нужный интерфейс. Студия переименовывает его на клиентской стороне. Скорее всего он называется IService1Callback.
     
    Подчеркивает красным - это не ошибка. Ошибка - это то, что пишется в окне Errors при попытке компиляции. :)
    • Помечено в качестве ответа SiberianWolf 16 октября 2010 г. 18:25
    16 октября 2010 г. 17:25
  • Большое спасибо.

    Нашел еще ошибку (по собственной невнимательности): реализацию колбэка вынес за namespace.

    16 октября 2010 г. 18:25