Not long ago I created a simple CRUD example using Silverlight 2.0 beta 2. I used Visual Studio 2008 and the ASP.NET Development Server. I wanted to test the same WCF web service with a different client (more on that soon), so I decided to deploy it to the instance of IIS 7.0 which comes with Windows Vista. I created a new web site on a different port than the default.
Nothing worked. Reason: although I have installed .NET 3.5 SP1 beta and Vista SP1 – which should do this automatically – the IIS 7 mime types and handler mappings were not configured for Silverlight and WCF. How to fix the mime type is here and the handler mappings, here.
The web service still didn’t work. I got:
A first chance exception of type ‘System.ServiceModel.ProtocolException’ occurred in System.ServiceModel.dll.
I changed the debug options to break on all managed exceptions, and got this further detail:
The remote server returned an unexpected response: (404) Not Found.
Problem: Silverlight is looking for a cross-domain policy file. The reason was that at this point I was still running the Silverlight app from the ASP.NET Development server, and it considered IIS to be on a separate domain. The 404 error does not make this obvious; but a quick Google for Silverlight 404 shows that this is a common problem.
Silverlight is designed to support cross-domain policy files in either Microsoft’s format (clientaccesspolicy.xml) or Adobe’s format (crossdomain.xml). If the service is just for Silverlight, use Microsoft’s format; otherwise I suggest adding both.
Nearly there; but I still had to fix SQL Server authentication. I normally use Windows authentication, and if you are using the ASP.NET Development server this just works. Move to IIS though, and it does not work unless you set up ASP.NET impersonation, or create a SQL Server login for the account under which the application pool is running. Oddly, when I tried the app without fixing the SQL Server login I still got a 404 exception; I’m not sure why.
Incidentally, I noticed that if you configure ASP.NET impersonation for a web site, the username and password gets written to web.config in plain text (bad). If you configure the application pool to run under a different account, the password is encrypted in applicationHost.config (better). In the end I decided to use good old SQL Server authentication.
One last tip: when debugging a web service, put the following attribute on the class which implements your ServiceContract:
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
Otherwise you get generic fault messages that don’t help much with debugging. Remove it though for release builds.
Once I’d fixed the SQL server login, everything was fine.