Visual Studio 2008 Walkthrough: Creating, Hosting and Using WCF Services with Silverlight 2

Before we Start

The final project is a sample that sends a string to WCF web service from Silverlight and gets a response back. 

Sample source code: http://blogs.msdn.com/nikola/attachment/8168735.ashx (Edit: see comments on how to change the source to work for localhost instead of public web site)

Edit: updated test link: http://www.nokola.com/SampleService/ServiceClientAppTestPage.aspx

This walkthrough is provided as-is, no warranties or rights.

Issues that this post will help you address

This post will help you with deployment, hosting and these 3 kind of common issues in particular:

 

1. The below error may appear when trying to host the web service on the internet.

This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.

Parameter name: item

 

2. Some 500. internal server errors like HTTP Error 500.19 - Internal Server Error. This can happen when you have several web.config files in nested directories (e.g. deploying service in nested folders on the web server)

 

3. UnexpectedHttpResponseCode: With this walkthrough you will not see some of the cross-domain errors that I encountered, like UnexpectedHttpResponseCode. This exception is thrown at the Silverlght client side and can happen either because of cross-domain issues or because the service is throwing exceptions when accessed. If the service works fine, then try adding crossdomain.xml file to the root of your web site, as described here: http://msdn2.microsoft.com/en-us/library/cc197955(VS.95).aspx. Note that two different port numbers on the same server count as two different domains. So you might be getting this error message in case the webservice runs on localhost:12340 and the site is at localhost:12345, for example during debugging.

Creating The Projects

Prerequisites:

· VS 2008

· Silverlight SDK: http://www.microsoft.com/downloads/details.aspx?FamilyId=4E03409A-77F3-413F-B108-1243C243C4FE&displaylang=en

 

Creating the Silverlight project

1. Open Visual Studio 2008

2. Click File, New Project. Select C# (or VB)

3. Click Silverlight and select Silverlight Application, name it ServiceClientApp. I also check Create Directory for Solution. Click OK.

4. Select Generate and HTML test page to host Silverlight within this project. Click OK.

5. Open Page.xaml, and add a text box for typing, a button and a textblock to display the result.

 

Your page.xaml should look something like this:

 

<UserControl x:Class="ServiceClientApp.Page"

   xmlns="http://schemas.microsoft.com/client/2007"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   Width="400" Height="300">

    <StackPanel x:Name="LayoutRoot" Background="White">

        <WatermarkedTextBox x:Name="boxTypeText" Watermark="Type a name here"></WatermarkedTextBox>

        <Button Content="Send to WCF web service" Width="200" x:Name="btnSend" Click="btnSend_Click" />

        <TextBlock x:Name="textResponse" Text="Response from WCF Service:"/>

    </StackPanel>

</UserControl>

 

6. In the code-behind file, add the even handler for the button:

 

    public partial class Page : UserControl

    {

        public Page()

        {

            InitializeComponent();

        }

        private void btnSend_Click(object sender, RoutedEventArgs e)

        {

        }

    }

}

 

Creating the service project

1. Right-click on the solution in solution explorer and select Add -> New Web Site

2. Select WCF Service and C# (or VB) for language

3. Name the website HelloWorldService

4. In the App_code folder change in IService.cs and Service.cs the GetData function to accept string instead of int:

public string GetData(string value)

 

5. Add a custom service host factory to Service.cs. We add this since WCF supports one base address only and some web servers return more. If we don’t add this, you may get the following exception when trying to access the web service:

This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.

Parameter name: item

 

Below is how my Service.cs ended up after adding a custom service host and factory. I decided to host the service here: http://www.nokola.com/SampleService/Service.svc

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.Text;

using System.ServiceModel.Activation;

// NOTE: If you change the class name "Service" here, you must also update the reference to "Service" in Web.config and in the associated .svc file.

public class Service : IService

{

      public string GetData(string value)

      {

            return string.Format("You entered: {0}", value);

      }

      public CompositeType GetDataUsingDataContract(CompositeType composite)

      {

            if (composite.BoolValue)

            {

                  composite.StringValue += "Suffix";

            }

            return composite;

      }

}

public class MyServiceHostFactory : ServiceHostFactory

{

    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)

    {

        return new CustomServiceHost(serviceType, new Uri("http://nokola.com/SampleService/Service.svc"));

    }

}

public class CustomServiceHost : ServiceHost

{

    public CustomServiceHost(Type serviceType, params Uri[] baseAddresses)

        : base(serviceType, baseAddresses) { }

    protected override void ApplyConfiguration()

    {

        base.ApplyConfiguration();

    }

}

 

6. In Service.svc make use of the factory:

<%@ ServiceHost Language="C#" Debug="true" Service="Service" Factory="MyServiceHostFactory" CodeBehind="~/App_Code/Service.cs" %>

 

7. In web.config update the wsHttpBinding to basicHttpBinding:

<endpoint address="" binding="basicHttpBinding" contract="IService">

 

Deploying and Hosting

 

Deploying the Service

1. Right-click on the HelloWorldService web site project, and select Publish Web Site

2. Select the settings for your web site and click OK. Make sure to publish to the same address as in MyServiceHostFactory that you created. In my case I published at http://nokola.com/SampleService

3. From your web site administration tools select the SampleService fodler to be an application, otherwise you might get something like this:

Server Error in '/' Application.

Configuration Error

Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

Parser Error Message: It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS.

 

4. Test the service by opening it in IE. In my case I tested by opening http://nokola.com/SampleService/Service.svc

If you see a page starting like this, then Congratulations! You’ve created your service successfully:

 

Service Service

You have created a service.

 

You probably noted that the title says “Service Service”, this is not because the system is very happy with your new creation (who knows) but also because your service is named “Service”.

 

Deploying the Silverlight Application

Before deploying the application we have to make some more updates so it can access the service correctly:

1. Right-click on the HelloWorldService web site in Solution Explorer and select Add Silverlight Link

2. Select ServiceClientApp (should be already selected), make sure that Add test page that references this control is checked and click Add

3. Build and re-publish the service. Test it again.

4. Try opening the web page from the web site. In my case it’s at http://nokola.com/SampleService/ServiceClientAppTestPage.html

You should see your Silverlight application at that point, and the button does nothing yet

5. Go back to Visual Studio and right-click the ServiceClientApp project in the Solution Explorer. Select Add Service Reference.

6. In the Address box type the address of your service. In my case I typed http://nokola.com/SampleService/Service.svc

7. Update the Page.xaml.cs to call the service. Here’s how I updated mine:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

namespace ServiceClientApp

{

    public partial class Page : UserControl

    {

        ServiceReference1.ServiceClient client;

        public Page()

        {

            InitializeComponent();

            client = new ServiceClientApp.ServiceReference1.ServiceClient();

            client.GetDataCompleted += new EventHandler<ServiceClientApp.ServiceReference1.GetDataCompletedEventArgs>(client_GetDataCompleted);

        }

        private void btnSend_Click(object sender, RoutedEventArgs e)

        {

            client.GetDataAsync(boxTypeText.Text);

        }

        void client_GetDataCompleted(object sender, ServiceClientApp.ServiceReference1.GetDataCompletedEventArgs e)

        {

            if (e.Error != null)

            {

                textResponse.Text = e.Error.Message;

            }

            else

            {

                textResponse.Text = e.Result;

            }

        }

    }

}

 

8. Rebuild and re-deploy the HelloWorldService web site.

 

Go to your test html (in my case http://nokola.com/SampleService/ServiceClientAppTestPage.html ), type “test” in the box and click Send to WCF web service.

If everything works OK you should see “You entered: test” below the button.

 

Congratulations!

Feedback is always welcome! If you enjoyed this walkthrough and want to see more like this please let me know or leave a comment.

Nikola

ServiceClientApp.zip