wsDualHttpBinding always timeout, while other services work as expected

3.8k views Asked by At

I currently develop several services (WCF) to work with TFS 2010.

Some of them use the event subscription tool, while others are consumed through the sharepoint portal, small wpf applications, etc.

I'm working on an application to administer some stuff in another server, such as send an IIS Reset request to the server, and I'm using wsDualHttpBinding so I can message the user the progress as everything happens, through callbacks.

But I can't even call the method in the service, because whenever the channel tries to open, I get timeout exceptions, no matter what my OpenTimeout is.

This is my config (client-side)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.net>
        <connectionManagement>
            <add maxconnection="200"   address="*"  />
        </connectionManagement>
    </system.net>
    <system.serviceModel>
        <bindings>
            <wsDualHttpBinding>
                <binding name="WSDualHttpBinding_IReset" closeTimeout="00:01:00"
                    openTimeout="00:02:00" receiveTimeout="00:10:00" sendTimeout="00:01: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="Windows" negotiateServiceCredential="true" />
                    </security>
                </binding>
            </wsDualHttpBinding>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IDeploy" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="1524288" maxReceivedMessageSize="1279748152"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
                    <readerQuotas maxDepth="32" maxStringContentLength="81925" maxArrayLength="163848"
                        maxBytesPerRead="9192" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="None">
                        <transport clientCredentialType="Windows" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="Windows" negotiateServiceCredential="true" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://tfsserver:8080/TFSFacade/DeployFacade.svc"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDeploy"
                contract="DeployFacade.IDeploy" name="WSHttpBinding_IDeploy" />
            <endpoint address="http://tfsserver:8080/DeployService/ResetService.svc"
                binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IReset"
                contract="ResetService.IReset" name="WSDualHttpBinding_IReset" />
        </client>
    </system.serviceModel>
    <appSettings>
        <add key="CopiaLocalRollback" value="true"/>
        <add key="CopiaLocalPublish" value="true"/>
        <add key="ModoDiagnostico" value="false" />
        <add key="TempoTimeout" value="300000" />
    </appSettings>
</configuration>

Server-side:

<?xml version="1.0"?>
<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>
    <system.serviceModel>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true">
            <baseAddressPrefixFilters>
                <add prefix="http://tfsserver:8080"/>
                <add prefix="http://tfsservices:8080"/>
                <add prefix="http://tfsservices:1001"/>
            </baseAddressPrefixFilters>
        </serviceHostingEnvironment>
        <bindings>
            <wsDualHttpBinding>
                <binding name="WSDualHttpBinding_ResetService" closeTimeout="00:01:00"
                openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01: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="Windows" negotiateServiceCredential="true" />
                    </security>
                </binding>
            </wsDualHttpBinding>
        </bindings>
        <behaviors>
            <serviceBehaviors>
                <behavior name="EventServiceBehavior">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                </behavior>
                <behavior name="">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service behaviorConfiguration="EventServiceBehavior" name="DeployService.ResetService">
                <endpoint address="" binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_ResetService"
                  contract="DeployService.Contracts.IReset" />
            </service>
        </services>
    </system.serviceModel>
    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
    </system.webServer>
</configuration>

Contracts:

[ServiceContract(SessionMode = SessionMode.Required,
             CallbackContract = typeof(IResetCallback))]
public interface IReset
{
    [OperationContract]
    void ExecutarIISReset();
}

[ServiceContract]
public interface IResetCallback
{
    [OperationContract(IsOneWay = true)]
    void PumpMessage(string message);

    [OperationContract(IsOneWay = true)]
    void PumpResponsiveMessage(ResponsiveMessage message);

    [OperationContract(IsOneWay = true)]
    void PumpLogDeployBEMessage(LogDeployBE message);

    bool Confirmar();

    ServidorModel[] GetServidores();
}

Service (Not posting the code since the problem happens before it's reached):

[AspNetCompatibilityRequirementsAttribute(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)] 
public class ResetService : IReset
{
    //Stuff here
}

In fiddler I get this on client-side:

7 202 HTTP tfsserver:8080 /DeployService/ResetService.svc 0 private resetman.vshost:9000

I get 202 several times, then time passes and the timeout occurs

Running fiddle on the server, I get absolutely nothing.

What may be happening?

EDIT: Weird, localhost works. Does wsDualHttpBinding need special permissions or something? Didn't find anything on the 'internets'

3

There are 3 answers

0
wal On

Since you are using wsDualHttpBinding then both your server and your client need to be reachable on the ports specified in your config. This is the reason it works on your local machine as you dont have any port issues. The timeout is consistent with a firewall blocking or your server unable to route back to your client.

If your client can easily be reached by adding a firewall or port forwarding rule then wsDualHttpBinding may still be suitable - otherwise using wsDualHttpBinding is probably not ideal. In this case you may need to have the client poll for messages instead of receiving them via the callback (ie client pulls messages instead of having them pushed via a callback)

See this post for more. and also this one.

0
tom redfern On

Try

  • ConcurrencyMode = ConcurrencyMode.Reentrant
  • InstanceContextMode = InstanceContextMode.Single
  • remove SessionMode.Required

on your service behaviour

0
Ankur Gupta On

I was stuck with the same problem. I have resolved the issue by passing my binding configuration to the service with the help of following code in client application. This will give you an idea about how to achieve your goal. It worked for me in most of my systems but it still gives the timeout problem in some systems. Possible cause unable to bind the port.

      Service objService = new Service(objClass, "WSDualHttpBinding_ISendChatService");
            WSDualHttpBinding binding = objService.Endpoint.Binding as WSDualHttpBinding;
            int portNumber = FreeTcpPort();
            string hostName = Dns.GetHostName();
            binding.ClientBaseAddress = new Uri("http://"+Dns.GetHostByName(hostName).AddressList[0].ToString()+":" + portNumber + "/");            
            objService.Start(name);


static int FreeTcpPort()
        {
            TcpListener l = new TcpListener(IPAddress.Loopback, 0);
            l.Start();
            int port = ((IPEndPoint)l.LocalEndpoint).Port;
            l.Stop();
            return port;
        }