0

Please help me!!!

I am trying to build an application which uses callbacks contracts.My app work fine both the client and the server on the same machine, but when i try to access the service from other machine i got an exception timeout(the operation din not complete within the allotted timeout).The client reads some values throw the service from the database which is on the server.I don't know where is my mistake.I have tried to put the client in a virtual machine, and the service(and database) on the real machine.

Here is my Server config file:

            <binding name="TrainService" closeTimeout="00:02:00" openTimeout="00:02:00"
                receiveTimeout="00:10:00" sendTimeout="00:02:00" bypassProxyOnLocal="false"
                transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00" />
                <security mode="None">
                    <message clientCredentialType="None" negotiateServiceCredential="true"
                        algorithmSuite="Default" />
                </security>
            </binding>
        </wsDualHttpBinding>
        <wsHttpBinding>
            <binding name="WSHttpBinding_ITrainService" closeTimeout="00:02:00"
                openTimeout="00:02:00" receiveTimeout="00:10:00" sendTimeout="00:02:00"
                bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                allowCookies="false">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00"
                    enabled="false" />
                <security mode="None">
                    <transport clientCredentialType="None" proxyCredentialType="None"
                        realm="" />
                    <message clientCredentialType="None" negotiateServiceCredential="true"
                        algorithmSuite="Default" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
  <client>
    <endpoint address="http://localhost:8732/Design_Time_Addresses/WCFandEFService/TrainService/"
      binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ITrainService"
      contract="TrainServiceRef.ITrainService" name="WSHttpBinding_ITrainService">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="net.tcp://localhost:8080/TcpService" binding="netTcpBinding"
      contract="TrainServiceRef.ITrainService" name="NetTcpBinding_ITrainService" />
    <endpoint address="http://localhost:8082/InterlockingService/Host/line"
      binding="wsDualHttpBinding" bindingConfiguration="LineService"
      contract="InterlockingServiceReference.ILineService" name="LineService">
      <identity>
        <userPrincipalName value="Romina-PC\Romina" />
      </identity>
    </endpoint>

    <endpoint address="http://localhost:8082/InterlockingService/Host/trains"
      binding="wsDualHttpBinding" bindingConfiguration="TrainService"
      contract="InterlockingServiceReference.ITrainService" name="TrainService">
      <identity>
        <userPrincipalName value="Romina-PC\Romina" />
      </identity>
    </endpoint>

  </client>

</system.serviceModel>

My client config file:

-->

            <binding name="TrainService" closeTimeout="00:01:00" openTimeout="00:01:00"
                receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
                transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                maxBufferPoolSize="52428800" maxReceivedMessageSize="6553600"
                messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="1638400"
                    maxBytesPerRead="4096" maxNameTableCharCount="1638400" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00" />
                <security mode="None">
                    <!--<message clientCredentialType="None" negotiateServiceCredential="true"
                        algorithmSuite="Default" />-->
                </security>
            </binding>
        </wsDualHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:8082/InterlockingService/Host/line"
            binding="wsDualHttpBinding" bindingConfiguration="LineService"
            contract="InterlockingServiceRef.ILineService" name="LineService">
            <identity>
                <userPrincipalName value="Romina-PC\Romina" />
            </identity>
        </endpoint>

        <endpoint address="http://localhost:8082/InterlockingService/Host/trains"
            binding="wsDualHttpBinding" bindingConfiguration="TrainService"
            contract="InterlockingServiceRef.ITrainService" name="TrainService">
            <identity>
                <userPrincipalName value="Romina-PC\Romina" />
            </identity>
        </endpoint>
    </client>
</system.serviceModel>

Thank you.

Those are the contracts: public interface ITrainServiceCallBack { [OperationContract (IsOneWay=true)] void OnTrainChangeState(TrainData train); }

//[ServiceContract(Name = "LineService", CallbackContract = typeof(ILineServiceCallBack))]
[ServiceContract(CallbackContract = typeof(ITrainServiceCallBack))]
public interface ITrainService
{
    [OperationContract]
    TrainData GetTrainData(string trainName);

    [OperationContract]
    bool ChangeTrainState_bool(ref TrainData train);

    [OperationContract]
    void ChangeTrainState(ref Trains_Detail train);
    [OperationContract]
    bool SubscribeToTrainChangeEvent();

    [OperationContract]
    bool UnSubscribeFromTrainChangeEvent();
    [OperationContract]
    TrainData TranslateTrainEntityToTrainData(Trains_Detail trainEntity);

    [OperationContract]
    IEnumerable<Trains_Detail> GetTrains();

    [OperationContract]
    IEnumerable<Trains_Detail> GetTrains_ByStation(int Statie_plecare, int Statie_sosire);
}

Method implementation:

using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using System.Data;

namespace WCFandEFService { // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "ProductService" in both code and config file together. //[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]

public partial class InterlockingService : ITrainService
{

    static List<ITrainServiceCallBack> subscribers_train = new List<ITrainServiceCallBack>();


    public bool TrainExists(string nrTren, InterlockingEntities database)
    {
        // Check to see whether the specified product exists in the database
        int numTrain = (from t in database.Trains_Details
                       where string.Equals(t.Nr_tren, nrTren)
                       select t).Count();

        return numTrain > 0;

    }


    public TrainData TranslateTrainEntityToTrainData(Trains_Detail trainEntity)
    {
        TrainData train = new TrainData();

        train.nrTren=trainEntity.Nr_tren;
        train.ora_Plecare= trainEntity.Ora_plecare;
        train.ora_Sosire=trainEntity.Ora_sosire;
        train.statie_Plecare=trainEntity.Statie_plecare;
        train.statie_Sosire=trainEntity.Statie_sosire;
        train.rang=trainEntity.Rang;
        train.observatii=trainEntity.Observatii;            
        train.RowVersion=trainEntity.RowVersion;

        return train;

    }

    #region ILineService Members



    public IEnumerable<Trains_Detail> GetTrains()
    {
        InterlockingEntities context = new InterlockingEntities();


        IEnumerable<Trains_Detail> result =
                (from t in context.Trains_Details
                 //where l.Station == station
                 select t);
        return result;

    }

     public IEnumerable<Trains_Detail> GetTrains_ByStation(int Statie_plecare,int Statie_sosire)
    {
        InterlockingEntities context = new InterlockingEntities();

        IEnumerable<Trains_Detail> result =
                (from t in context.Trains_Details
                 where t.Statie_plecare==Statie_plecare && t.Statie_sosire==Statie_sosire
                 select t);
        return result;

    }



    public TrainData GetTrainData(string trainNr)
    {
        InterlockingEntities context = new InterlockingEntities();
        Trains_Detail trainInDB =
             (from t
              in context.Trains_Details
              where String.Compare(t.Nr_tren, trainNr) == 0
              select t).FirstOrDefault();
        if (trainInDB == null)
        {

            throw new Exception("No line cu numele " + trainInDB.Nr_tren);

        }

        context.Detach(trainInDB);
        return TranslateTrainEntityToTrainData(trainInDB);
    }

    public bool ChangeTrainState_bool(ref TrainData train)
    {
        InterlockingEntities context = new InterlockingEntities();
        String trainName = train.nrTren;
        //int lineStation = line.station;
        Trains_Detail trainInDB =
             (from t
              in context.Trains_Details
              where String.Compare(t.Nr_tren, trainName) == 0
              select t).FirstOrDefault();

        if (trainInDB == null)
        {
            throw new Exception("No train cu numele " + trainInDB.Nr_tren);
        }

        context.Detach(trainInDB);


        trainInDB.Nr_tren = train.nrTren;
        trainInDB.Ora_plecare=train.ora_Plecare;
        trainInDB.Ora_sosire=train.ora_Sosire;
        trainInDB.Statie_plecare=train.statie_Plecare;
        trainInDB.Statie_sosire=train.statie_Sosire;
        trainInDB.Rang=train.rang;

        trainInDB.RowVersion = train.RowVersion;

        context.Attach(trainInDB);

        context.ObjectStateManager.ChangeObjectState(trainInDB, System.Data.EntityState.Modified);
        context.SaveChanges();
        train.RowVersion = trainInDB.RowVersion;
        context.Dispose();
        raiseTrainChangeState(TranslateTrainEntityToTrainData(trainInDB));
        return true;
    }


    public void ChangeTrainState(ref Trains_Detail train)
    {
        using (var context = new InterlockingEntities())
        {
            context.Attach(train);
            context.ObjectStateManager.ChangeObjectState(train, EntityState.Modified);
            context.SaveChanges();
        }
    }
   }


    public bool SubscribeToTrainChangeEvent()
    {
        try
        {
            ITrainServiceCallBack callback = OperationContext.Current.GetCallbackChannel<ITrainServiceCallBack>();

            if (!subscribers_train.Contains(callback))
            {
                subscribers_train.Add(callback);
            }
            return true;
        }
        catch (Exception)
        {

            return false;
        }


    }

    public bool UnSubscribeFromTrainChangeEvent()
    {
        try
        {
            ITrainServiceCallBack callback = OperationContext.Current.GetCallbackChannel<ITrainServiceCallBack>();
            subscribers_train.Remove(callback);

            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    #endregion




    private void raiseTrainChangeState(TrainData train)
    {
        subscribers_train.AsParallel().ForAll(callback =>
        {
            if (((ICommunicationObject)callback).State == CommunicationState.Opened)
            {
                callback.OnTrainChangeState(train);

            }
            else
            {
                subscribers_train.Remove(callback);
            }
        });
    }






}

}

Annymmor A
  • 1
  • 1
  • 3

3 Answers3

1

The operation contract(s) in the Callback contract should be marked IsOneWay = true, and should return void - not all the operation contracts in the service.

Also, I had a similar problem using duplex contracts over NetTcpBinding. I resolved this by setting the OperationTimeout value on the proxy (in my case, to 5 minutes). I set it programatically by casting my channel to the IContextChannel interface on the client when creating the channel. You should probably be able to do the same in the client config file.

My code:

((IContextChannel)myChannel).OperationTimeout = new Timespan(0, 5, 0);
Tim
  • 28,212
  • 8
  • 63
  • 76
  • I have modified all that you have suggested, but it doesn't work.The same error message(for 10 minutes -> the operation din not complete within the allotted timeout).Other suggestions? Thanks for reply – Annymmor A Jun 02 '11 at 18:00
  • Operations on the callback contract for WSDualHttpBinding *do not* need to be marked as one way. – carlosfigueira Jun 02 '11 at 18:12
0

Your endpoint address in the client and the server specifies "localhost" as the machine name. If they're in different machines, the client won't be able to talk to the service. Try changing it to the actual machine name where the server is located.

Update: here's an example of a WSDualHttpBinding working with non-one-way operations on both contract and callback contract. WSDualHttpBinding does not require that operations on the callback contract to be one way. PollingDuplexHttpBinding (for Silverlight) does, but that's another story.

using System;
using System.IO;
using System.Reflection;
using System.ServiceModel;
using System.Threading;

public class StackOverflow_6216605_751090
{
    [ServiceContract(CallbackContract = typeof(ITestCallback))]
    public interface ITest
    {
        [OperationContract]
        int Add(int x, int y);
        [OperationContract]
        void CallMe(int numberOfTimes);
    }
    [ServiceContract]
    public interface ITestCallback
    {
        [OperationContract]
        string Hello(string name);
    }
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class Service : ITest
    {
        public int Add(int x, int y)
        {
            Console.WriteLine("In a Request/Reply operation on server: {0} + {1}", x, y);
            return x + y;
        }

        public void CallMe(int numberOfTimes)
        {
            Console.WriteLine("In another request/reply operation on server, which will call the client.");
            ITestCallback callback = OperationContext.Current.GetCallbackChannel<ITestCallback>();
            ThreadPool.QueueUserWorkItem(delegate
            {
                for (int i = 0; i < numberOfTimes; i++)
                {
                    Console.WriteLine("Received from client: {0}", callback.Hello("Server"));
                }
            });
        }
    }
    [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class ClientCallback : ITestCallback
    {
        static int count = 0;
        public string Hello(string name)
        {
            Console.WriteLine("In a client operation, name = {0}", name);
            return string.Format("[{0}] Hello, {1}", ++count, name);
        }
    }
    static void PrintUsage()
    {
        string programName = Path.GetFileName(Assembly.GetEntryAssembly().CodeBase);
        Console.WriteLine("Usage: {0} <options>", programName);
        Console.WriteLine("Examples:");
        Console.WriteLine("  Starting the server: {0} -server", programName);
        Console.WriteLine("  Starting the client: {0} -client <serverMachineName>", programName);
    }
    public static void Main(string[] args)
    {
        if (args.Length < 1)
        {
            PrintUsage();
            return;
        }

        if (args[0].Equals("-server", StringComparison.OrdinalIgnoreCase))
        {
            string serviceAddress = "http://" + Environment.MachineName + ":8000/Service";
            ServiceHost host = new ServiceHost(typeof(Service), new Uri(serviceAddress));
            host.AddServiceEndpoint(typeof(ITest), new WSDualHttpBinding(WSDualHttpSecurityMode.None), "");
            host.Open();
            Console.WriteLine("Host opened, press ENTER to close");
            Console.ReadLine();
            host.Close();
        }
        else if (args.Length > 1 && args[0].Equals("-client", StringComparison.OrdinalIgnoreCase))
        {
            string serviceAddress = "http://" + args[1] + ":8000/Service";
            ClientCallback clientCallback = new ClientCallback();
            DuplexChannelFactory<ITest> factory = new DuplexChannelFactory<ITest>(
                clientCallback,
                new WSDualHttpBinding(WSDualHttpSecurityMode.None),
                new EndpointAddress(serviceAddress));
            ITest proxy = factory.CreateChannel();
            Console.WriteLine("Simple Request/Reply: {0}", proxy.Add(3, 4));
            Console.WriteLine("Now calling an operation on the server which will cause callbacks");
            proxy.CallMe(10);
            Console.WriteLine("Press ENTER to close");
            Console.ReadLine();
        }
        else
        {
            PrintUsage();
        }
    }
}
carlosfigueira
  • 85,035
  • 14
  • 131
  • 171
  • Hi @carlosfigueira, would you mind showing an example on where and how the WSHttpBinding support request/response kind of communication? – SaravananArumugam Jun 02 '11 at 17:24
  • I am not sure how would the request/response type message exchange be counted as Duplex. Please refer http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/15841cf6-b6bb-492a-915c-340b1cbb890d/ for similar conversation. – SaravananArumugam Jun 02 '11 at 17:38
  • By duplex, it means that the service can send requests to the clients at any time - i.e., the client doesn't need to do some thing like polling the server for messages. WSDualHttpBinding actually creates a server on the client side, and in the initial handshake the client sends the server the address it will be listening to the messages. – carlosfigueira Jun 02 '11 at 17:55
  • I absolutely agree to this definition. My argument is you are sending the request in a channel and listening to it in different one. That's the reason, the WSHttpBinding creates OneWayBindingElement. Ofcourse you are receiving a response in different channel. But it can't be considered to be request/response MEP right. it is duplex. – SaravananArumugam Jun 02 '11 at 18:00
  • Well I have tried to change, but no result.Other suggestions?Thank you – Annymmor A Jun 02 '11 at 18:01
  • @Saravanan, there's no WSHttpBinding in this question, it's about WSDualHttpBinding. – carlosfigueira Jun 02 '11 at 18:13
  • @Annymmor, there are other things you can be wrong, depending on your contracts. If the service implementation tries to call the client operation, and the concurrency mode is set to Single (the default), then you may have a timeout as well. After changing the machine names (on *both* client and server), you can try using some tool such as Fiddler to see if there are requests actually being sent from the client, and see if the service is responding with a 200 (OK) or with some other error (and the response body may give you more information on your problem). – carlosfigueira Jun 02 '11 at 18:16
  • That was a typo. I agree it is not about WSHttpBinding. It is WSDualHttpBinding we are talking about. – SaravananArumugam Jun 02 '11 at 18:21
  • I install Fiddler on the server machine and the client machine.On the client machine I see that the request is sent to server, but on the server machine the Fidler doesn't show anything.What I am missing? – Annymmor A Jun 02 '11 at 19:09
  • Do you get a valid response from the request you see from the client machine? Also, I noticed that you updated your question, but the endpoint address still shows "localhost". Did you update them as well? – carlosfigueira Jun 02 '11 at 19:47
  • I get a 502 response on the server.And timeout.I have changed the localhost adress. – Annymmor A Jun 03 '11 at 05:58
  • 502 == Bad Gateway. Try checking the proxy settings on your machine (if the client and the server are in the same network try disabling the proxy to see if it helps. – carlosfigueira Jun 03 '11 at 14:40
  • It was the firewall and the service behaviour not configured right.Thanks guys – Annymmor A Jun 07 '11 at 14:28
-1

Check if you have marked your operation contract as one way. Its usual to get a timeout in dual http binding where people fail to mark the contract as one way.

[OperationContract(IsOneWay = true)]

EDIT

Please place the following line in the service contract's behavior.

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)] 

For our reference, consider posting your service contract structure and the operation contract's implementation.

SaravananArumugam
  • 3,680
  • 6
  • 33
  • 45
  • All my operation contracts?Because I put to all isoneway=true and i get the following error:System.InvalidOperationException: Operations marked with IsOneWay=true must not declare output parameters, by-reference parameters or return values. – Annymmor A Jun 02 '11 at 15:38
  • wsDualHttpBinding is duplex communication binding. In essence, it would call in one channel and receive in another. So when you make a call, you should expect you are simply making a forward only call (Reply would be received in a different channel), and won't expect any out put as a response for your call. – SaravananArumugam Jun 02 '11 at 17:14
  • WSDualHttpBinding does support non-one-way (i.e., request/reply) operations, you shouldn't need to set the operations to one-way. – carlosfigueira Jun 02 '11 at 17:16
  • You may refer to http://saravananarumugam.wordpress.com/2011/04/08/simple-duplex-contract-implementation/ for an idea of this binding and duplex channel connection. – SaravananArumugam Jun 02 '11 at 17:16
  • Whichever call you are going to use in the WSDualHttpBinding has to be a one way operation. Request/response is a different message exchange pattern than the duplex. – SaravananArumugam Jun 02 '11 at 17:36
  • I put to the callback interface the method to oneway=true, but i've got the same error.(the operation din not complete within the allotted timeout...).Thanks for advice. – Annymmor A Jun 02 '11 at 18:00
  • I have add the contracts.I appreciate ypu help me.I need it a lot.It is urgent.I was looking for a solution all the day.If you want I can send you the code, but I do not know where to put it. – Annymmor A Jun 02 '11 at 18:26
  • If I add it in the interface it results an error.I put it in the implementation class, but I have the following error: "The open operation did not complete within the allotted timeout of 00:00:59.9843750. The time allotted to this operation may have been a portion of a longer timeout." (System.TimeoutException) Exception Message = "The open operation did not complete within the allotted timeout of 00:00:59.9843750. The time allotted to this operation may have been a portion of a longer timeout.", Exception Type = "System.TimeoutException" – Annymmor A Jun 02 '11 at 18:43
  • I have no idea what i can try – Annymmor A Jun 02 '11 at 18:43