Thursday, July 5, 2012

Silverlight and WCF NET.TCP Binding

A lot of people on the internet are having issues with Silverlight 5, WCF (Callback Contract) and nettcpbinding. They end up with the following error message

Could not connect to *****. The connection attempt lasted for a time span of 00:00:00.0990056. TCP error code 10013: An attempt was made to access a socket in a way forbidden by its access permissions.. This could be due to attempting to access a service in a cross-domain way while the service is not configured for cross-domain access. You may need to contact the owner of the service to expose a sockets cross-domain policy over HTTP and host the service in the allowed sockets port range 4502-4534.

I was not able to find even a single working example available on the internet for the same. This blog post might help those looking for a solution to the problem and a working example.

First of all silverlight does not support all the bindings available in WCF. If you want to use a WCF service in your silverlight application which requires a session to be created or if you want to use a WCF service with a callback contract in your silverlight application then you are required to use either NET.TCP binding or PoolingDuplexHttp binding.

If you are planning to host your WCF Service on a Windows Server, you must make sure that it supports TCP. To use NET.TCP binding you need to have IIS7 (available on windows server 2008).

Note: IIS6 and below do not support TCP related bindings.

Also silverlight application can communicate with a WCF service over TCP by only using a port in the range of 4502 - 4534. All the ports in this range are not accessible by default and that is why you get the error message mentioned above.

You need to do the following to get it working
  1. Make sure you have enabled Windows Communication Foundation Non-HTTP Activation.
  2.  To enable WCF Non-HTTP Activation go to Control Panel -- Programs -- Turn Windows features on and off. Expand Microsoft .NET Framework 3.5.1, check the WCF Non-HTTP Activation and click on OK.
  3. Using the IIS Manager then enable NET.TCP binding on your website. To enable NET.TCP binding right click on your website (through IIS Manager) and click on Edit Bindings... then Add a new Binding of type: net.tcp and with binding information: 4502:* and click OK. Again right click on your website and then go to Manage Web Site -- Advanced Settings... Then in the list of enabled protocols change http to http,net.tcp and click on OK.
  4. Now create an exception for the port (that you have planned to use, in my example it is 4502) in the Windows Firewall so that communication over that port is not blocked (creating an exception in the Windows Firewall should work in most of the cases).
  5. Then you have to create a clientaccesspolicy.xml file and place it inside the root folder (C:\inetpub\wwwroot or C:\inetpub\vhosts\default\htdocs).
  6. You are good to go. Just use the WCF service in your Silverlight 5 project as you will do in case of ASP.NET or WPF.
 Also silverlight does not support security over NET.TCP binding so you must disable it in the web.config of your WCF service.

<netTcpBinding>
    <binding name="silverlight" portSharingEnabled="true">
        <security mode="None"/>
    </binding>
</netTcpBinding>

 

The clientaccesspolicy.xml will look like the following

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
<socket-resource port="4502" protocol="tcp"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy> 

Here is the working application(WPF Desktop Client, Silverlight 5 Web Client using WCF - NET.TCP binding)