Update 1 (Sept. 17, 2010):
While the part below about using SLSvcUtil.exe to generate the service reference undoubtedly still works, it is no longer necessary. The RTM version of the Windows Phone Developer Tools now properly supports right-clicking on your game project's "References" item in the Solution Explorer and adding a Service Reference that way. ChannelFactory and related methods remain unsupported. For more details see http://msdn.microsoft.com/en-us/library/ff637320(VS.95).aspx (Networking in Silverlight for Windows Phone), which appears to have been updated since I first wrote this post.
There’s been much ado about how to get a WCF service working in XNA on WP7. Most solutions involve some form of creating a Silverlight something or other and slinging WCF in from there. Those days are over. Here’s what you need: the Windows Phone Developer Tools and Visual Web Developer 2010 Express (both are free; I’ve also tested this with Visual Studio 2010 Ultimate which, not surprisingly, handled it just fine :) ).
First, let’s create a web service. Open up Visual Web Developer 2010 Express. Go to “File->New Project”. It may have you in Visual Basic. This would probably work fine, but I work much more in C# so I switched to Visual C# under Installed Templates and then chose “WCF Service Application”. I set a name (I chose WcfXnaTestService) and hit “OK”. Like magic, my web service sprang forth. The default service doesn’t do much – it takes in an int and spits back a string – but who cares! Go to the “Build” menu and choose “Build WcfXnaTestService” (or whatever you named your service). Then go to “Debug->Start Debugging”. This should start up a local webserver and open up a copy of either Internet Explorer or something called WCF Test Client.
If you get IE, click on the file that says “Service1.svc”. This will open a webpage telling you about your service. At the top will be a line that looks something like: “svcutil.exe http://localhost:64152/Service1.svc?wsdl”. Right click on the link, and choose “Copy Shortcut”.
If you get WCF Test Client, on the left you will see “My Service Projects”. If it has a little + next to it, click it to expand it. You will then see something that looks something like “http://localhost:64152/Service1.svc”. (Note: 64152 is just the port it happened to assign me on this run, you could get any high number). Right click on the localhost address and choose “Copy Address”.
Now don’t close any of that, whichever one you got. Just leave it be. We want that server to keep running until we’re completely and totally done with this entire tutorial. So minimize it or whatever, but leave it all running (including Visual Web Developer too, of course).
At this point you need to open a command prompt. Yep, land of dragons and wizards. Press the Windows Key + R to open up a Run dialog box (this works in both Windows 7 and Windows Vista; alternately, go to the Start menu and choose Run). Type “cmd” and hit enter. This will bring up a command prompt with you in your user directory. Assuming you have the tools installed in the default location, if you have a 32-bit version of Windows installed, you will run the following command:
C:\Program Files\Microsoft SDKs\Windows Phone\v7.0\Tools\SlSvcUtil.exe http://localhost:64152/Service1.svc?wsdl
if you have 64-bit Windows, you will instead run:
C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Tools\SlSvcUtil.exe http://localhost:64152/Service1.svc?wsdl
You’ll notice that we’re using that address we copied earlier. You can simply right click in the command prompt window and choose “Paste” to insert the correct one for you (if you copied the command from this tutorial, you just need to change the port (that 64152 number) to whichever one your computer decided to open for you). Note that if you do paste from earlier and you got WCF Test Client, you will need to add “?wsdl” to the end of the url just as it appears above.
Hit enter. It’ll tell you something like “Attempting to download metadata from ‘http://localhost…. etc. etc. DISCO (seriously) … Generating files… (file names).
It should give you Service1.cs and ServiceReferences.ClientConfig assuming you didn’t change anything.
Now, open up Visual Studio 2010 Express for Windows Phone and make a new XNA game. I’m going to assume you know how to do this. Once you have your XNA game, add those files it generated to your game project (you can drag and drop or add them by right clicking on the game project in the Solution Explorer and choosing “Add->Existing Item…” or however you want). Note: not the content project, the game project. Once they are all in, you must do two things. First, right click on ServiceReferences.ClientConfig and set choose “Properties”. Set the “Build Action” to “Content” and set “Copy to Output Directory” to “Copy if newer”. I’m not sure that you have to set it to “Content” but you must set it to copy into the output directory to make sure it’s included in the XAP file. Next, switch back to the Solution Explorer and right click on “References” in your game project. You will need to add references (if you don’t already have them) to System.Net, System.Runtime.Serialization, and System.Servicemodel. Try compiling your game. It should compile. If not, add more references (make educated guesses based on the error messages – but those were all I had to add). Then you can add an instance of the WCF service to your game. I used the stock game that comes with the Windows Phone Developer Tools just to keep things simple. I added a SpriteFont to my content project, added the following field to my Game1 class:
string result = "";
then in LoadContent I loaded my sprite font and instantiated my Service1Client using the parameter-less constructor:
service1Client = new Service1Client();
I then typed in,
at which point auto completion shows up and says to hit TAB to add in the rest and then to hit TAB again to generate the callback method. Two tabs produced:
service1Client.GetDataCompleted += new EventHandler<GetDataCompletedEventArgs>(service1Client_GetDataCompleted);
with a new method:
void service1Client_GetDataCompleted(object sender, GetDataCompletedEventArgs e)
// It started with the below line, which I eliminated and replaced with the rest of what appears
// throw new NotImplementedException();
result = e.Result;
I added lines in Draw to draw the string called result and then in update I added:
if (gameTime.TotalGameTime.TotalSeconds > 15 && !hasSentRequest)
hasSentRequest = true;
This waits for 15 seconds then starts the process of getting data from the WCF service (which is still running, right? You didn’t close it accidentally?). This will return quite quickly, setting what was our empty result string to “You entered: 30” which will appear right on screen courtesy of SpriteBatch which has been drawing the empty string this whole time and now draws the newly populated one.
So there you have it. I won’t really go into detail about all the ways I tried that didn’t work. I finally got to a point where I was trying to implement a ChannelFactory(TChannel) which gave me a NotSupportedException when I did implement it by hand (because it wasn’t implementing itself) and that triggered a memory that led me to MSDN and this page: http://msdn.microsoft.com/en-us/library/ff637320(VS.95).aspx (“Networking for Windows Phone”, specifically the “Implementation Differences” heading) which in turn led me to this page: http://msdn.microsoft.com/en-us/library/cc197958(VS.95).aspx (“Using SLsvcUtil.exe to Access a Service”). Once I found that, it was done. A quick search on my computer found the location of SLsvcUtil.exe (which you saw earlier in this post). A quick run showed me it was a command line utility. And then a quick foray into the command prompt showed me how it worked.
One final note: unless and until you are hosting this on a “real” website (or at least on a fixed port on your computer rather than one that will most likely change each time you close Visual Web Developer and then restart it later), you’ll need to remember to open up ServiceReferences.ClientConfig and change the port number to whatever port you happened to get on the new run. It’s in the address in the “endpoint” tag – it’s a small file so you’ll see it right away. Sorry it’s been a while. I’ve been working on something “big” that I hope to have done and ready to go soon. Until next time, good luck!