Silverlight with WCF Services and SQL LocalDB Development and Deployment using CassiniDev.


Problem: You are required to deploy a Silverlight application that accesses a database via WCF Services onto a standalone computer that does not have IIS, IIS Express, or SQL Server Express installed.  Your end users are people with very limited or no real technical background that find even simple day-to-day IT tasks difficult. What database and web server do you use, and how can you make the installation as easy as possible for your end users with little, or preferably no configuration?

Solution.

  • Install SQL Server 2012 or higher on your development computer.
  • Connect to the LocalDb server instance in management studio using: (localdb)\v11.0.
  • Create a new query and enter the following command to create     your database:

    create database databaseName on (name=’databaseName’, filename=’fileLocation\fileName.mdf’)

  • Create your tables.
  • Create a new Visual Studio Silverlight with WCF RIA Services project.
  • Right click on the web project and select Manage NuGet Packages…
  • Select the online option and type entityframework.
  • Install EntityFramework.
  • Add a model.  The server name should be: (localdb)\v11.0.
  • Build your project.
  • Create your domain service.
  • Build your project.
  • In your Silverlight application import the System.ServiceModel.DomainServices.Client namespace, and the namespace of your web project.
  • Create a member variable for your domain context and IEnumerable of your domain object.
  • In the appropriate method that will instantiate the domain service add the relevant EntityQuery and LoadOperation lines of code.
  • Add you method that will handle the LoadOperation.Completed event, check that args is not nothing.
  • Use your entities as required.
  • Now add a Windows Form application.
  • Download and install CassiniDev.
  • In your Windows Forms application add a reference to the CassiniDev4-lib.dll.
  • For the tutorial on Using CassiniDev to host ASP.NET in your application.
  • Build your solution.
  • Copy the deployable portions of the web project into the WebContent folder located in the Windows Forms executable’s root folder.

On the client computer that you are going to deploy the solution on you will need to install:

  • Silverlight 5;
  • the .NET Framework 4.02 update (NDP40-KB2544514-x86-x64.exe);
  • and the SQL Server Local Database (SqlLocalDB.msi).

There is the Express Edition of InstallShield which is free to use.  Use this to create a Basic MSI project that will silently install the above components, and copy your application onto the client computer.  Create a desktop shortcut.  Run the executable from the shortcut to test that the application is working.

Custom tool error: Failed to generate code for the service reference …


Within a Windows Phone 7 Silverlight client, when updating a service reference I frequently receive the following error message: “Custom tool error: Failed to generate code for the service reference ”. Please check other error and warning messages for details.” When I get this error, the code generator fails to generate the Reference.cs file. This has the knock on effect of generating a number of errors as my service reference is no longer recognised by VS2010.

Completely removing the service references, deleting the bin, obj folders and service reference folders, and removing the service reference pointers in the project file and readding the service references has no effect at all. The custom tool still fails to generate the Reference.cs file. That means that the problem has to lie with the WCF Service.

I will now investigate the WCF Service, and see if this yields any clue as to what is going on.

It is indeed the service, there is something wrong with my deployment. My initial thinking is that there are some missing dependencies that my service relies on. And I am right. There were some missing DLLs, and data files that the service depends upon.

Another problem has arisen, in that the Exception policy for the Enterprise Framework as set in the Web.config file is being set more than once. This generates an error, and yet it is only located in one place! The simple fix is to simply comment the policy field out in the config file.

Testing the deployed service now works in the WCF Test Client, after modifying the client config to increase the timeouts, maximum buffer size, and maximum message received size.

Now that have I my deployed service working, surely I can create my service reference and have the custom tool generate the source code for the Reference.cs file right? No. Hmmm, this is rather frustrating. But never mind, there is a solution. I just have to rack my brains a little harder.

I have tried to delete the service reference and recreate it with a different filename as some suggest on WCF forums, but this hasn’t worked for me. Time for a cup of tea and some thinking time.

Finally!!!

I have found the cause of the problem. Team Foundation Server was intefering with the regeneration of the service reference. To solve this issue, I deleted the bin folder, the obj folder, the service reference client config file, the service references, and the service reference folder. I then saved the solution and checked in the changes to Team Foundation Server, and confirmed the pending deletions. Then I recreated the services, and lo and behold the Reference.cs file was created with the generated source code.

In summary, when your client fails to create a service reference the first thing to check is that the service is working correctly using the WCF Test Client. Once you have established that the service is working, update your service reference. If the source code for the Reference.cs file has not been generated by the custom tool, delete the bin folder, obj folder, service reference folder with all its contents, and the client service config file. Save the project and check in the project confirming all deletions. Then proceed to add the service references. At this point you should have the fully generated service references with source code and the basic client service config file. The final stage is to modify the bindings in the config file to include the timeouts set to “00:10:00”, the MaxBufferSize set to 2147483647 and set the MaxReceivedMessageSize to 2147483647.

A very painful excersise, but one with a happy ending:)

Update: 2011-05-27

This issue raised its ugly head again. I followed the steps above to fix the issue but they didn’t work in my project. So I created a new project that was not in TFS and added the service reference and it worked!

I had a look at the ServiceReferences.ClientConfig and noticed that the basicHttpBinding and the client endpoint were missing for the reference I was trying to add. So I added these entries to the ServiceReferences.ClientConfig file and then added the service reference, and sure enough the References.cs file was generated correctly.

WCF and the CommunicationException


When working with Windows Communication Foundation (WCF) Services, you will no doubt encounter various System.ServiceModel exceptions. The one error I normally find very hard to debug and solve is the System.ServiceModel.CommunicationException (CommunicationException crossed a native/managed boundary). The error message associated with this exception is {“The underlying connection was closed: The connection was closed unexpectedly.”}.

The problem raises its ugly head after a service method has been added or updated, and appears to occur during serialization and deserialization. As the serialized object is being deserialized, the object being deserialized is not of a known type. This results in the above error message being thrown. The solution to this problem is to make sure that you are returning the correct type. There are attributes that you can set on your contract called KnownType and ServiceKnownType. But in my case, setting these attributes had no effect on solving this particular issue.

My solution was to create a separate method in the service passing back the correct type. This worked but created a secondary issue. The secondary issue was still a System.ServiceModel.CommunicationException (CommunicationException crossed a native/managed boundary). But this time the error message was “The maximum message size quota for incoming messages (65535) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.”

To solve this secondary issue was very straight forward. In the WCF Test Client, I right clicked on the Client Config file and from the popup menu selected Edit with SvcConfigEditor. This opens the Service Configuration Editor application with the client config file used by the test client. I then navigated to Bindings and clicked on the binding for my service which happened to be using BasicHttpBinding because it had to work on a Windows Phone 7 Device. Under the general settings, I then proceeded to change both the MaxBufferSize and MaxReceivedMessageSize to the maximum value of 2147483647 which is 2 GB.

I then saved the config file and re-ran my WCF Test, and hey-presto, it worked.

So the moral of the story is this. If you get a CommunicationException, make sure that you are returning the correct type and that it is a known type, and within the client config files make sure that the MaxBufferSize and MaxReceivedMessageSize is appropriate for the server response.