Real World WCF on Windows Phone 7

I have already covered using WCF from Windows Phone 7 with my quick walk-through , but now, some months later, I have now shipped an application that uses it, and learned a few things on the way that help get a connection to the local WCF host reliably.

Name Resolution

My app requires connection to a WCF service hosted on a PC on the user's home network, so it asks the user for the name of the PC then connects. What could possibly go wrong? Er quite a lot actually. Although this worked well for me, it turns out it doesn't work well for many paying customers, who have to specify the actual IP address of the PC instead of its name. Further digging revealed why I was in the minority: my Actiontec router (supplied by Verizon for my Fios connection) actually includes a real-life DNS Server. It is auto-configuring, and fills itself based on broacasts on the local network, so I never realized it even existed. Once I turned it off, I became much more like my customers, and my phone app would never connect to my server by name.

After asking around at work I found that WP7, when on wi-fi, will use DNS and WINS to find network endpoints by name, but that's all. As few home networks run DNS or WINS servers that proves to be rather a problem for apps like mine. On most home networks name resolution is done on PCs by NetBIOS or UPNP, but WP7 has neither. As third party phone apps cannot get to sockets then there is no other way to resolve names.

Getting A Connection After Waking

The wi-fi connection is dumped when the screen turns off, so when you wake a WP7 device the radio has to come up, find your wi-fi router and have a chat. This takes time, and the time seems to vary by device, by network, and by the phase of the moon. To try and make things a little more reliable my app does the following, in an effort to get the wi-fi connection up and my WCF connection going as promptly as possible:

Try the WCF connection

if it fails then

    call NetworkInterface.NetworkInterfaceType (and ignore the result)

    set a timer

        Try the WCF connection

        if it works then exit and do real work

    until the timer hits 30 seconds

then if still nothing, ask the user to retry. This results in a 97% success rate in attaching in to the WCF service in 30 seconds, at least on my network and devices. YMMV. (By "Try the WCF connection" I mean make a call through the service proxy).

Random Exceptions during Exit

Through my LittleWatson diagnostics I would occasionally get crashes during app exit that would never repro with a debugger attached. The callstack was always the same, vis:

at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously)
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously, Exception exception)
at System.ServiceModel.Channels.HttpOutput.WebRequestHttpOutput.GetOutputStreamAsyncResult.OnGetRequestStream(IAsyncResult result)
at System.Net.Browser.ClientHttpWebRequest.<>c__DisplayClass6.<InvokeGetRequestStreamCallback>b__4(Object state2)
at System.Threading.ThreadPool.WorkItem.doWork(Object o)
at System.Threading.Timer.ring()

I never succeeded in stopping this from happening, and could not catch the exception as it is on someone else's thread, so I modified my LittleWatson to ignore this specific callstack. I can only speculate that when an async call comes in at the wrong point during process shutdown, something bad happens. (Others have reported a similar stack on vanilla http requests as well).

I hope these hints help you in your WCF endeavors. Of course if your WCF service is on the actual internet none of this applies (except the random exception) as DNS to live internet sites and wi-fi wake-up is not a problem.