April showers bring May flowers! Congratulations to our Creative Challenge: April Showers winner, member antaver59.
by antaver59
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.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
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?
Short answer:
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.
Long answer:
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"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*" />
</allow-from>
<grant-to>
<socket-resource port="4502-4534" protocol="tcp" />
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
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 Scrosati
Developer, Silverlight WCF team
Did you know it is now easier to debug the server side PollingDuplex in Silverlight 4? With the addition of tracing, you can now get a peek at what is happening internally within your service. Traces from PollingDuplex will include information about what failed in communicating with your clients and how it was handled.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Enabling tracing is as simple as adding this configuration section in your Web.config file.
<?xml version="1.0"?>
<configuration>
<system.diagnostics>
<sources>
<source name="System.ServiceModel.PollingDuplex" switchValue="Information">
<listeners>
<add type="System.Diagnostics.DefaultTraceListener" name="Default"/>
<add name="xml"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData=".\MyPollingDuplexServiceTraces.svclog" type="System.Diagnostics.XmlWriterTraceListener" name="xml"/>
</sharedListeners>
<trace autoflush="true"/>
</system.diagnostics>
</configuration>
Once configured, restart your service. If you use IIS, updating the Web.config will automatically recycle your service. Voila! Tracing is enabled.
Using this configuration, your traces are stored in XML format in a file called MyPollingDuplexServiceTraces.svclog. You can review the content of this file using Service Trace Viewer (SvcTraceViewer.exe). This tool is part of the .NET Framework SDK and is part of a standard Visual Studio install. Below is a sample screen capture of a trace file I generated from a service that seemed to deny clients to connect.
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
From this, I see that the server is overwhelmed by the number of incoming new client connections. From there, I can try to find a cause. Maybe the server hardware is too slow? Or is the MaxPendingSessions throttle modified to a value that is too low? I also see there is a MaxSessionsPerAddress throttle that is hit. Maybe there is a client that is attempting to open and maintain a large number of connections? In this case, my service is using a Polling Duplex binding set with very low MaxPendingSessions.
Our team hopes you will find this addition useful. Your feedback is always welcome, so please peruse the commenting section. Happy tracing!
-Christopher Scrosati
Developer, Silverlight WCF team