10 min read

(For more resources on silverlight, see here.)

Introduction

Looking at the namespaces and classes in the Silverlight assemblies, it’s easy to see that there are no ADO.NET-related classes available in Silverlight. Silverlight does not contain a DataReader, a DataSet, or any option to connect to a database directly. Thus, it’s not possible to simply define a connection string for a database and let Silverlight applications connect with that database directly.

The solution adds a layer on top of the database in the form of services. The services that talk directly to a database (or, more preferably, to a business and data access layer) can expose the data so that Silverlight can work with it. However, the data that is exposed in this way does not always have to come from a database. It can come from a third-party service, by reading a file, or be the result of an intensive calculation executed on the server.

Silverlight has a wide range of options to connect with services. This is important as it’s the main way of getting data into our applications. In this article, we’ll look at the concepts of connecting with several types of services and external data.

We’ll start our journey by looking at how Silverlight connects and works with a regular service. We’ll see the concepts that we use here recur for other types of service communications as well. One of these concepts is cross-domain service access. In other words, this means accessing a service on a domain that is different from the one where the Silverlight application is hosted. We’ll see why Microsoft has implemented cross-domain restrictions in Silverlight and what we need to do to access externally hosted services.

Next, we’ll talk about working with the Windows Azure Platform. More specifically, we’ll talk about how we can get our Silverlight application to get data from a SQL Azure database, how to communicate with a service in the cloud, and even how to host the Silverlight application in the cloud, using a hosted service or serving it from Azure Storage.

Finally, we’ll finish this chapter by looking at socket communication. This type of communication is rare and chances are that you’ll never have to use it. However, if your application needs the fastest possible access to data, sockets may provide the answer.

Connecting and reading from a standardized service

Applies to Silverlight 3, 4 and 5

If we need data inside a Silverlight application, chances are that this data resides in a database or another data store on the server. Silverlight is a client-side technology, so when we need to connect to data sources, we need to rely on services. Silverlight has a broad spectrum of services to which it can connect.

In this recipe, we’ll look at the concepts of connecting with services, which are usually very similar for all types of services Silverlight can connect with. We’ll start by creating an ASMX webservice—in other words, a regular web service. We’ll then connect to this service from the Silverlight application and invoke and read its response after connecting to it.

Getting ready

In this recipe, we’ll build the application from scratch. However, the completed code for this recipe can be found in the Chapter07/SilverlightJackpot_Read_Completed folder in the code bundle that is available on the Packt website.

How to do it…

We’ll start to explore the usage of services with Silverlight using the following scenario. Imagine we are building a small game application in which a unique code belonging to a user needs to be checked to find out whether or not it is a winning code for some online lottery. The collection of winning codes is present on the server, perhaps in a database or an XML file. We’ll create and invoke a service that will allow us to validate the user’s code with the collection on the server. The following are the steps we need to follow:

  1. We’ll build this application from scratch. Our first step is creating a new Silverlight application called SilverlightJackpot. As always, let Visual Studio create a hosting website for the Silverlight client by selecting the Host the Silverlight application in a new Web site checkbox in the New Silverlight Application dialog box. This will ensure that we have a website created for us, in which we can create the service as well.
  2. We need to start by creating a service. For the sake of simplicity, we’ll create a basic ASMX web service. To do so, right-click on the project node in the SilverlightJackpot. Web project and select Add | New Item… in the menu. In the Add New Item dialog, select the Web Service item. We’ll call the new service as JackpotService. Visual Studio creates an ASMX file (JackpotService.asmx) and a code-behind file (JackpotService.asmx.cs).
  3. To keep things simple, we’ll mock the data retrieval by hardcoding the winning numbers. We’ll do so by creating a new class called CodesRepository.cs in the web project. This class returns a list of winning codes. In real-world scenarios, this code would go out to a database and get the list of winning codes from there. The code in this class is very easy. The following is the code for this class:

    public class CodesRepository
    {
    private List<string> winningCodes;
    public CodesRepository()
    {
    FillWinningCodes();
    }
    private void FillWinningCodes()
    {
    if (winningCodes == null)
    {
    winningCodes = new List<string>();
    winningCodes.Add("12345abc");
    winningCodes.Add("azertyse");
    winningCodes.Add("abcdefgh");
    winningCodes.Add("helloall");
    winningCodes.Add("ohnice11");
    winningCodes.Add("yesigot1");
    winningCodes.Add("superwin");
    }
    }
    public List<string> WinningCodes
    {
    get
    {
    return winningCodes;
    }
    }
    }

  4. At this point, we need only one method in our JackpotService. This method should accept the code sent from the Silverlight application, check it with the list of winning codes, and return whether or not the user is lucky to have a winning code. Only the methods that are marked with the WebMethod attribute are made available over the service. The following is the code for our service:

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class JackpotService : System.Web.Services.WebService
    {
    List<string> winningCodes;
    public JackpotService()
    {
    winningCodes = new CodesRepository().WinningCodes;
    }
    [WebMethod]
    public bool IsWinningCode(string code)
    {
    if(winningCodes.Contains(code))
    return true;
    return false;
    }
    }

  5. Build the solution at this point to ensure that our service will compile and can be connected from the client side.
  6. Now that the service is ready and waiting to be invoked, let’s focus on the Silverlight application. To make the service known to our application, we need to add a reference to it. This is done by right-clicking on the SilverlightJackpot project node, and selecting the Add Service Reference… item.
  7. In the dialog that appears, we have the option to enter the address of the service ourselves. However, we can click on the Discover button as the service lives in the same solution as the Silverlight application. Visual Studio will search the solution for the available services. If there are no errors, our freshly created service should show up in the list. Select it and rename the Namespace: as JackpotService, as shown in the following screenshot. Visual Studio will now create a proxy class:

  8. The UI for the application is kept quite simple. An image of the UI can be seen a little further ahead. It contains a TextBox, where the user can enter a code, a Button that will invoke a check, and a TextBlock that will display the result. This can be seen in the following code:

    <StackPanel>
    <TextBox x_Name="CodeTextBox"
    Width="100"
    Height="20">
    </TextBox>
    <Button x_Name="CheckForWinButton"
    Content="Check if I'm a winner!"
    Click="CheckForWinButton_Click">
    </Button>
    <TextBlock x_Name="ResultTextBlock">
    </TextBlock>
    </StackPanel>

  9. In the Click event handler, we’ll create an instance of the proxy class that was created by Visual Studio as shown in the following code:

    private void CheckForWinButton_Click(object sender,
    RoutedEventArgs e)
    {
    JackpotService.JackpotServiceSoapClient client = new
    SilverlightJackpot.JackpotService.JackpotServiceSoapClient();
    }

  10. All service communications in Silverlight happen asynchronously. Therefore, we need to provide a callback method that will be invoked when the service returns:

    client.IsWinningCodeCompleted += new EventHandler
    <SilverlightJackpot.JackpotService.
    IsWinningCodeCompletedEventArgs>
    (client_IsWinningCodeCompleted);

  11. To actually invoke the service, we need to call the IsWinningCodeAsync method as shown in the following line of code. This method will make the actual call to the service. We pass in the value that the user entered:

    client.IsWinningCodeAsync(CodeTextBox.Text);

  12. Finally, in the callback method, we can work with the result of the service via the Result property of the IsWinningCodeCompletedEventArgs instance. Based on the value, we display another message as shown in the following code:

    void client_IsWinningCodeCompleted(object sender,
    SilverlightJackpot.JackpotService.
    IsWinningCodeCompletedEventArgs e)
    {
    bool result = e.Result;
    if (result)
    ResultTextBlock.Text = "You are a winner! Enter your data
    below and we will contact you!";
    else
    ResultTextBlock.Text = "You lose... Better luck next time!";
    }

  13. We now have a fully working Silverlight application that uses a service for its data needs. The following screenshot shows the result from entering a valid code:

How it works…

As it stands, the current version of Silverlight does not have support for using a local database. Silverlight thus needs to rely on external services for getting external data. Even if we had local database support, we would still need to use services in many scenarios. The sample used in this recipe is a good example of data that would need to reside in a secure location (meaning on the server). In any case, we should never store the winning codes in a local database that would be downloaded to the client side.

Silverlight has the necessary plumbing on board to connect with the most common types of services. Services such as ASMX, WCF, REST, RSS, and so on, don’t pose a problem for Silverlight. While the implementation of connecting with different types of services differs, the concepts are similar.

In this recipe, we used a plain old web service. Only the methods that are attributed with the WebMethodAttribute are made available over the service. This means that even if we create a public method on the service, it won’t be available to clients if it’s not marked as a WebMethod. In this case, we only create a single method called IsWinningCode, which retrieves a list of winning codes from a class called CodesRepository. In real-world applications, this data could be read from a database or an XML file. Thus, this service is the entry point to the data.

For Silverlight to work with the service, we need to add a reference to it. When doing so, Visual Studio will create a proxy class. Visual Studio can do this for us because the service exposes a Web Service Description Language (WSDL) file. This file contains an overview of the methods supported by the service. A proxy can be considered a copy of the server-side service class, but without the implementations. Instead, each copied method contains a call to the actual service method. The proxy creation process carried out by Visual Studio is the same as adding a service reference in a regular .NET application.

However, invoking the service is somewhat different. All communication with services in Silverlight is carried out asynchronously. If this wasn’t the case, Silverlight would have had to wait for the service to return its result. In the meantime, the UI thread would be blocked and no interaction with the rest of the application would be possible.

To support the asynchronous service call inside the proxy, the IsWinningCodeAsync method as well as the IsWinningCodeCompleted event is generated. The IsWinningCodeAsync method is used to make the actual call to the service. To get access to the results of a service call, we need to define a callback method. This is where the IsWinningCodeCompleted event comes in. Using this event, we define which method should be called when the service returns (in our case, the client_IsWinningCodeCompleted method). Inside this method, we have access to the results through the Result parameter, which is always of the same type as the return type of the service method.

See also

Apart from reading data, we also have to persist data. In the next recipe, Persisting data using a standardized service, we’ll do exactly that.

LEAVE A REPLY

Please enter your comment!
Please enter your name here