Sometimes stepping away from a problem and returning to attempt a solution at a later time provides the clarity needed to overcome obstacles and drive to resolution. When that fails, a desperate email to a smarter colleague often does the trick.
My first attempt to call a web service from Silverlight 1.1 was quickly rebuffed by the .NET framework as an attempt to implement cross-domain scripting, which is strictly forbidden in the Silverlight sandbox. I thought I heard a comment about that in my review of the MIX07 videos, and sure enough, there’s a discussion of this about midway through the DEV22 talk.
While cross-domain web service calls are not permitted, the speaker commented that calls to web services within the context of the same web are permitted. Sure enough, Silverlight projects do permit you to add a web reference, and under the covers, a Silerlight friendly proxy is generated via slwsdl.exe when you do so. This proxy handles all the details of JSON that are required by Silverlight but needn’t concern you if you’re like me and just trying to get some data from the server from whence you came.
Attempts to add a web service directly to the Silverlight project quickly ran afoul of a lack of a suitable template in the Add New Item dialog
If this doesn’t makes immediate sense, remind yourself of where Silverlight is running (namely, on the client) and you’ll see why it doesn’t make much sense for it to provide a web service. It took a little while for me to come to this realization, but eventually I did (or as they say up here, dawn breaks over Marblehead…) So what to do?
Well, I found it simplest to add a web site to the solution that contains my Silverlight project and build out the web service there. But how then do you include the Silverlight content, and after that, how do you debug interactively? The first step was to add a Silverlight link to the nascent web site – Orcas provides a easy way to do this via the context menu you get when you right-click the web project:
From here, it was just a matter of adding a simple ASP.NET web service and then adding a web reference to it back up in the Silverlight project. slwsdl.exe dutifully generated a Silverlight friendly proxy and I was able to see the method on my web service in all its glory. However, I kept getting a System.Net.WebException or a System.InvalidOperationException whenever I tried to call it.
To spare you the details of my thrashing about for an answer, I’ll cut straight to the solution. It turns out that all I needed to do was uncomment a single line embedded in the web service. The line in question is the lower of the 2 listed below:
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
When I added the System.Web.Script.Services.ScriptService attribute to the web service class, everything worked just fine (see my note above about remembering where Silverlight runs and marble heads.) I could even set breakpoints on both sides of the service call and debug successfully.
This got me through the major obstacle of not being able to connect my app to its data, which will enable me to return the focus to Silverlight’s controls in my next posting.