As part of Silverlight 4, developers can now use the NetTcp framing protocol for their web services. This is an addition that we expect a lot of you will find useful. However, many of you will probably hit the dreaded CommunicationException that lurks the unsuspecting developer as soon as he tries to establish that first connection from their Silverlight client to the service.
You probably have seen this exception message before:
Could not connect to net.tcp://localhost:4502/MyService. The connection attempt lasted for a time span of 00:00:00.4270427. 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.
This fairly long exception message comes to “there probably is not an adequate cross-domain policy for the service endpoint you are trying to access”. The Silverlight runtime requires all network communications to be authorized. This is done by retrieving a policy file to associate with a remote server before doing the actual communication. Hard core details about the mechanism can be obtained in the MSDN article entitled Network Security Access Restriction in Silverlight.
So how do you solve this fast and easy?
Create a file named clientaccesspolicy.xml with the file content described below and host it on an HTTP server at http://<<YourNetTcpIPAddress>>:80/clientaccesspolicy.xml.
For NetTcp connection, you must use a HTTP based socket policy.
If you already have HTTP web services in place, you simply will add a few lines to your clientaccesspolicy.xml file and you *should* be done. Otherwise, you need to create a file named clientaccesspolicy.xml that is served via HTTP at the base IP address of your service on the standard HTTP port 80.
Noticed I said base IP address here? Internally, the policy file is retrieved by the first IP address your domain name resolves to. So if your HTTP domain name does not resolve to the same IP address as your NetTcp service, you will need some workaround. One solution could be an adaptation of Carlos Figueira REST-based policy server.
The content of your clientaccesspolicy.xml for debugging can be the one shown here. This policy is very lax though, and as great as it is for debugging purpose, it will let any clients access your service in production. You should therefore tinker with it and adapt it to your specific needs before deployment.
<?xml version="1.0" encoding="utf-8"?>
<domain uri="*" />
<socket-resource port="4502-4534" protocol="tcp" />
Once you have created your policy file and hosted it, test if it is retrievable by opening your browser and pointing it to http://<<YourNetTcpIPAddress>>:80/clientaccesspolicy.xml. Your browser should show you the content of your policy file. If this is the case, your Silverlight client should be free to talk with your NetTcp service!
-Christopher ScrosatiDeveloper, Silverlight WCF team