The question got me thinking about how does one connect to a legacy WCF in a LightSwitch application? Many shops have legacy web services which they may want to use from LightSwitch application.
Because I’ve implemented WCF solutions in the past, I thought connecting to a WCF service from LightSwitch would be a piece of cake. As it turned out, it became a learning experience as I needed to solve a few problems I hadn’t encountered before. Because of the amount of content, I plan to make two posts to explain how I solved the problem and some of the issues I encountered.
The scenario is a business needs to get current pricing information for a product. The user wants to have product price information updated from a LightSwitch screen when user clicks a button. On the button click, the screen’s code connects to a web service to get current product pricing and updates the product table.
In this blog post I’ll discuss creating the WCF service and a proxy to that service which you can use in LightSwitch.
In the next blog post, I’ll show you how to connect to the WCF service from a LightSwitch screen and update the product table.
Creating the WCF Service
Because I’ll be creating a WCF service and deploying the service to IIS on my local development box, I first start Visual Studio 2010 with administration rights.
Next I create a blank solution called Product.Wcf
When creating a WCF solution, I prefer to define one assembly for the Interface file so the service and client code can use the same interface definition. For this demo I’ll simplify the solution and put the interface and the service code into the same project.
Add a WCF Service Library project to the Product.Wcf solution. Call it Product.Wcf.Service:
Delete the App.config, IService1.cs and Service1.cs files which Visual Studio added to the project;
Add two files to the project: IProductService.cs and ProductService.cs.
I want two methods for this WCF demo- GetProductPriceUpdate() and GetAllProductPriceUpdate().
I want the GetProductPriceUpdate() to return price information using a passed in product identifier.
I want GetAllProductPriceUpdate() to return a collection of products with price updates.
I want the returned data contained in an object called ProductPriceInfo. ProductPriceInfo holds the product number and the new list price and standard price for the product.
With these requirements in mind, the IProductsService.cs file looks like this:
For the service implementation, I’ll simulate reading results from a back end database by just returning a fixed result set. The simple service implementation becomes:
GetProductPriceUpdate returns a price update for product “FR-R928-58”, otherwise it returns nothing.
GetAllProductPriceUdpate() returns price updates for three products.
With the WCF service implementation defined, I want to deploy the WCF service to my development machine’s IIS server.
First create new project of type WCF Service Application and call it Product.Wcf.WEB
Delete the IService1.cs and Servcie1.svc.cs files Visual Studio includes in the project and rename Service1.svc to ProductService.svc
Next, add a reference to the Product.Wcf.Service assembly from the Product.Wcf.Service project.
Next I open the ProductService.svc file and change the Service tag which reference the fully qualified name of the service code implementation:
Publish the WCF Service
The next step is to publish the web site. On my development machine, I entered the selections highlighted below:
Finally, start IIS manger to configure the site and test it.
When you first start IIS manager after publishing, you should see a folder labeled ProductService under the Default Web Site. Right click this folder and click the Convert to Application in the pop up context menu. The icon should change from a folder to a Site icon:
Next, configure the site to enable directory browsing:
With the ProductService site selected in the left pane, double click Directory Browsing.
Then click Enable in the Directory Browsing dialog:
Next click Browse to start an instance of Internet Explorer:
You should see the following in Internet Explorer.
Assuming all is configured correctly, you should see the following when you click ProductService.svc:
Write down the line circled above, you’ll need it in a moment.
Test the WCF Service
At this point, your web service is deployed and running. It’s always a good practice to test the code works, so let’s next create a simple console application to test the WCF service.
Add a new project to your solution- create a Console Application project and call it Product.WcfConsoleTest
Now, start a Visual Studio 2010 Tools command prompt. If you haven’t done this before, navigate to:
Start-> All Program -> Microsoft Visual Studio 2010 -> Visual Studio Tools -> Visual Studio Command Prompt (2010)
In the command prompt, navigate to the directory of your ConsoleTest project.
Then run the command you saw above in the Internet Explorer window.
Svcutil generates a file ProductWcfService.cs which contains the proxy code to connect to your WCF service. Add the ProductWcfService.cs file to your ConsoleTest project:
Next, add the System.ServiceModel and System.Runtime.Serialization assemblies to your ConsoleTest project references:
Next, write some code to test the WCF service in Program.cs:
This simple test creates an instance of the ProductService proxy, using the address of the WCF service which you saw in Internet Explorer above. The test then verifies the GetProductPrice returns a null ProductPriceInfo for a product other than “FR-R92B-58”. It then checks that GetAllProductProiceUpdate() returns three ProductPriceInfo, as implemented in our service.
After running this test, I thought, “Great! Now I can use the generated ProductWcfService.cs proxy code in my LightSwitch application”.
Well, I found out this was a very wrong assumption. First, when I tried to add a reference to an assembly containing this proxy to a LightSwitch project, Visual Studio showed the reference added, then in a few seconds removed it. Uh?!? I thought.
How to create a proxy you can use in LightSwitch
I fiddled around and soon realized the generated proxy code I used in the ConsoleTest project (generated by SVCUTIL.exe) cannot be used in a LightSwitch application, which is in reality a Silverlight application. I also found Silverlight requires a different version of the ServiceModel and Runtime.Serialization assemblies. And Silverlight requires the proxy to have asynchronous interfaces on the method calls. SVCUTIL creates synchronous method calls which won’t work in the LightSwitch environment.
After debugging in LightSwitch and exploring deeper, I found several pages which helped me come up with a solution. Here are references to pages which helped me and which you may want to read and drill deeper:
Using WCF Async pattern with Silverlight 3, Russell East’s blog
Silverlight 4 Synchronous WCF Service Calls, Benjamin Day’s blog
I discovered one way to create a usable proxy is by using the utility SLsvcutil.exe. I also learned I needed to call the WCF methods asynchronously. Because I want to hide the complexity of asynchronous calls from the LightSwitch code, I decided to write a façade class. A proxy to a proxy you might say
I also learned you should use a Silverlight Class library instead of a regular .NET Class library project in order to pick up references to the correct versions of the ServiceModel and Runtime.Serialization assemblies.
With the above in mind, add another project to the Product.Wcf solution. The project type is a Silverlight Class Library. Call the new project Product.Wcf.LSProductProxy:
Delete file Class.cs from the Product.Wcf.LSProductProxy project.
Add references to the ServiceModel and Runtime.Serialization assemblies. Notice the version numbers of these assemblies are 188.8.131.52. A little later as you’re working in the LightSwitch project, you’ll notice these are the same versions used by LightSwitch.
Next, in the Visual Studio 2010 command prompt, navigate to the directory of your Product.Wcf.LSProductProxy project. Run the SLSvcUtil.exe utility to generate a proxy usable in a Silverlight environment. On my machine, the SLSvcUtil.exe is located here:
c:\Program files (x86)\Microsoft SDKs\Silverlight\v4.0\Tools\
Add the generated file, ProductWcfService.cs, containing the proxy to the WCF service to your project.
Add another file called LSProxy.cs to your project. LSProxy will implement the calls to the WCF service and encapsulate the complexities of managing asynchronous method calls.
Here is the implementation of LSProxy:
In lines 27 and 28, the constructor wires up the event handlers for the asynchronous calls:
In line 22 and 23, the constructor initializes an AutoResetEvent for each asynchronous method:
The following is what happens when the LightSwitch application makes a WCF service call. For example, when the LightSwitch code calls LSProxy.GetProductPriceUpdate the following code executes:
The LightSwitch code calls LSProxy.GetProductPriceUpdate(string product). This method calls the WCF asynchronous method GetProductPriceUpdateSAsync(product) implemented in the generated code file, ProductWcfService.cs. A call to the WCF service is initiated and control returns immediately to LSProxy.GetProductPriceUpdate. The thread which makes the call to GetProductUpdateAsync blocks waiting for a signal from the AutoResetEvent (_autoResetEventGetProductPriceUpdate.WaitOne).
The thread executing LSProxy.GetProductPriceUdpate is the UI thread that is running the LightSwitch screen. Note that as this thread is blocked, this can block the LightSwitch application. Handling this problem may be as simple as providing a timer in the WaitOne call, or some more complex solution such as showing a pop up display with animation which the user can cancel may be needed for very long running processes—a topic for a future blog post.
When the WCF service returns data to the proxy, the data comes in on a different threat of execution and runs _proxy_GetProductPriceUpdateCompleted. This method copies the received data into the private member variable and unblocks the thread which called GetProductPriceUpdate.
Being unblocked, the main thread gets the data from the member variable and returns the data to the LightSwitch application.
In this post I demonstrated how to create a simple WCF service, deploy it, test it from a console application, and create a proxy to the service which you can use in a LightSwitch application.
In my next post, I’ll show how to use the proxy to make WCF service calls and update data within LightSwitch.
Project source files ProjectWcfSolution.zip