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)

1 comment:

  1. Hi Arshdeep

    Your post looks like it could help me, but I *think* you are posting more about the service than the Silverlight client? My problem is that I have a service produced by a "wizard" in the Dynamics Ax Client tool, and so I have little control over that!

    I can communicate with it with no problem from a Windows forms app, but I can't get my Silverlight client to talk to it.

    If I add a Service Reference to my Silverlight project in VS2010, it discovers the service with no problems, but fails to generate any binding code in ServiceReferences.ClientConfig - I assume because netTcp is apparently still "not supported" by Silverlight. When I run the project I get an error as follows:

    "Could not find default endpoint element that references contract ... servicename ... in the ServiceModel client configuration section"

    The only way I can get the functionality to work is to create an intermediate .Net SOAP service which will communicate happily with the Silverlight client. I then use this "intermediate" service to communicate with the remote WCF service - it all works fine but very slowly, and really there has to be a better way of doing this! With this setup I did originally get the "cross-domain" errors, but have got rid of those via a suitable clientaccesspolicy document.

    Do you have any suggestions? I believe that if the application targets "Silverlight 5" in the project settings, it references the file silverlightconfig2.xsd, which only contains data for basicHttp and custom bindings. If I target .Net 4 it references DotNetConfig35.xsd which contains data for 20 different bindingfs, including netTcp.

    Any hints would be very welcome!

    Ade

    ReplyDelete