views:

579

answers:

3

Hi Folks,

I have created a web application with a Silverlight project embedded in it, using VS 2008 SP 1, and the Silverlight 3 tools, on Vista and Windows 7.

The duplex service code:

    [ServiceContract(Namespace = "cotoco", CallbackContract = typeof(IDuplexClient))]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class DuplexServer
{
private IDuplexClient _client;
private string _message;
private int _messageCounter;

private Timer _timer;

public DuplexServer()
{
}

#region IDuplexServer Members

[OperationContract(IsOneWay = true)]
public void SendEcho(string message)
{
    _client = OperationContext.Current.GetCallbackChannel<IDuplexClient>();
    _message = message;

    _timer = new Timer();
    _timer.Interval = 2000;
    _timer.Enabled = true;
    _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
    _timer.Start();
}

void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
    _client.ReturnEcho(string.Format("Duplex Echo {0}: {1}", _messageCounter, _message));

    _messageCounter++;
    if (_messageCounter > 5)
        _timer.Dispose();
}

    #endregion
}

[ServiceContract]
public interface IDuplexClient
{
    [OperationContract(IsOneWay = true)]
    void ReturnEcho(string message);
}

The duplex config section:

<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="DuplexServerBehavior"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> <services> <service behaviorConfiguration="DuplexServerBehavior" name="DuplexServer"> <endpoint address="" binding="wsDualHttpBinding" contract="DuplexServer" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> </system.serviceModel>

I have setup a Duplex service in the client application as follows:

        Binding svcBinding;
        EndpointAddress svcAddress;

        svcBinding = new PollingDuplexHttpBinding() { UseTextEncoding = true };
        svcAddress = new EndpointAddress("http://localhost/CTC.Test.WCF.Server/DuplexServer.svc");
        _duplex = new DuplexServerClient(svcBinding, svcAddress);

I have used a Simplex service in tandem with this, and calls to the Simplex service hit the breakpoints setup on the server and i can step through.

Calls to the Duplex service do not hit the breakpoints, although no error is raised on the client. If i inspect the HTTP traffic with Fiddler, i can see hundreds of 202 requests being fired after the initial request - i assume these are the polling requests.

Initial Duplex Request:

POST http://localhost/CTC.Test.WCF.Server/DuplexServer.svc HTTP/1.1 Accept: / Content-Length: 665 Content-Type: application/soap+xml; charset=utf-8 UA-CPU: x86 Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; (R1 1.6); SLCC1; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618) Host: cotocovista4.cotoco.local Connection: Keep-Alive Pragma: no-cache

<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope"&gt;&lt;s:Header&gt;&lt;a:Action s:mustUnderstand="1">urn:IDuplexServer/SendEcho</a:Action><netdx:Duplex xmlns:netdx="http://schemas.microsoft.com/2008/04/netduplex"&gt;&lt;netdx:Address&gt;http://docs.oasis-open.org/ws-rx/wsmc/200702/anonymous?id=ae3e3139-0df8-41eb-97db-69c2c48782b7&lt;/netdx:Address&gt;&lt;netdx:SessionId&gt;43f9e320-cde3-4e21-a748-e5b29c10ee25&lt;/netdx:SessionId&gt;&lt;/netdx:Duplex&gt;&lt;a:To s:mustUnderstand="1">http://cotocovista4.cotoco.local/CTC.Test.WCF.Server/DuplexServer.svc&lt;/a:To&gt;&lt;/s:Header&gt;&lt;s:Body&gt;&lt;SendEcho&gt;&lt;message&gt;Message!&lt;/message&gt;&lt;/SendEcho&gt;&lt;/s:Body&gt;&lt;/s:Envelope&gt;

Subsequent Duplex Requests:

POST http://localhost/CTC.Test.WCF.Server/DuplexServer.svc HTTP/1.1 Accept: / Content-Length: 588 Content-Type: application/soap+xml; charset=utf-8 UA-CPU: x86 Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; (R1 1.6); SLCC1; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618) Host: cotocovista4.cotoco.local Connection: Keep-Alive Pragma: no-cache

<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope"&gt;&lt;s:Header&gt;&lt;a:Action s:mustUnderstand="1">http://docs.oasis-open.org/ws-rx/wsmc/200702/MakeConnection&lt;/a:Action&gt;&lt;a:To s:mustUnderstand="1">http://cotocovista4.cotoco.local/CTC.Test.WCF.Server/DuplexServer.svc&lt;/a:To&gt;&lt;/s:Header&gt;&lt;s:Body&gt;&lt;wsmc:MakeConnection xmlns:wsmc="http://docs.oasis-open.org/ws-rx/wsmc/200702"&gt;&lt;wsmc:Address&gt;http://docs.oasis-open.org/ws-rx/wsmc/200702/anonymous?id=ae3e3139-0df8-41eb-97db-69c2c48782b7&lt;/wsmc:Address&gt;&lt;/wsmc:MakeConnection&gt;&lt;/s:Body&gt;&lt;/s:Envelope&gt;

Does anyone know why this would happen, i thought I'd finally sussed the last problem when it stopped throwing connection exceptions....

Regards

Tris

Update: I have tried recreating this in the following project types: WCF Application, Web Application, Web Project. I have succeeded in implementing the MS Example that uses WCF Message's for the Duplex parameters without problem, but i was looking for a rapid way of assembling duplex web services using WSDL.

A: 

Do you know if the calls are actually getting through, and just not hitting your breakpoints? (You can test for this by inserting some other side effects, such as logging to a text file or something like that.) I ask this because I've run into exactly the same problem in the past, where breakpoints on WCF duplex services hosted within IIS aren't hit, even though the calls were getting made. I ended up having to switch to a self-hosted service to get around the problem. I filed this as a bug at MS, and they've indicated that it will be resolved in the .NET 4.0/VS2010/Silverlight 4.0 timeframe. I'd post the links, etc., but I can't find them right now.

My best suggestion, if this is an option for you, and if the problem is just that the breakpoints aren't getting hit, is either to move to VS2010, or move to a self-hosted service.

Ken Smith
I've put exceptions in the DuplexServer constructor and in all the web methods, and would expect that to cause a critical failure somewhere, but it carried on regardless. I haven't done any tracing though. I'll look into it.
Ok - I've added tracing, and it is definitely not getting hit.
Ok - I was using a Web Application, and have switched to a Web Project using InstanceContextMode.SingleInstance. It now hits the service class constructor once (Other instance modes do not). But it still does not hit the messages members.
Hmmmm . . . have you tried getting rid of the simplex service and only accessing the duplex service? I had the same arrangement on my current project at one point, but it was causing a variety of difficulties, so I moved everything over to a single duplex service, and that seemed to help matters. Worth a shot, perhaps.
Ken Smith
Yes, i have removed the simplex service. I have also tried this with a variety of projects - Web Application, Web Project, and WCF Project. Still no success.
I have also created web services using both an Interface implementation and a non interface implementation, and still have nothing coming off the server.
I have also tried this project on two seperate computers, one Vista, one Windows 7. Same results.
A: 

You may take a look at this blog post, download the sample code and try it.

Darin Dimitrov
Hi, thanks, i've already managed to successfully implement that example. It uses System.ServiceModel.Channels.Message as a parameter though which will require additional effort and manual data transformation at both ends - which i'm trying to avoid.
+1  A: 

So - i managed to finally get it working using the following web config section, and adjusting the client side accordingly:

<system.serviceModel>

<extensions>
  <bindingElementExtensions>
    <add name="pollingDuplex"
         type="System.ServiceModel.Configuration.PollingDuplexElement, System.ServiceModel.PollingDuplex"/>
  </bindingElementExtensions>
</extensions>

    <bindings>
        <customBinding>
            <binding name="DuplexConfig">
                <binaryMessageEncoding/>
                <pollingDuplex maxPendingSessions="2147483647" maxPendingMessagesPerSession="2147483647" inactivityTimeout="02:00:00" serverPollTimeout="00:05:00"/>
                <httpTransport/>
            </binding>
        </customBinding>
    </bindings>

    <behaviors>
        <serviceBehaviors>
            <behavior name="CTC.Test.WCF.Server.DuplexServiceBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="true"/>
                <serviceThrottling maxConcurrentSessions="2147483647"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>

    <services>
        <service behaviorConfiguration="CTC.Test.WCF.Server.DuplexServiceBehavior" name="CTC.Test.WCF.Server.DuplexService">
            <endpoint address="" binding="customBinding" bindingConfiguration="DuplexConfig" contract="CTC.Test.WCF.Server.IDuplexService"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>

</system.serviceModel>

If anyone can explain why this worked, but using wsDualHttpBinding did not, that would be really helpful. :)

(Also - why is that displayed in a code block? :/ )

Regards

Tristan

QUESTION: Also - using this method, it seems to maintain an open connection, rather than the mass 202 spam that i was getting using wsDualHttpBinding. Is this correct? Does this suck up the connection pool? And is there any way to use this PollingDuplexBinding option directly?