Accessing Data Using Silverlight

In this lesson of the Silverlight tutorial, you will learn...
  1. About how data is serialized when transported over the Web
  2. To access data stored on a Web server by calling a Web service or WCF service
  3. To manage data by using LINQ

This lesson will introduce the ability to play various types of multimedia sources in a Silverlight application.

Serialization

The Web is a stateless environment. In a typical Web communication scenario, a request for a resource is made by a client by the client passing a message to the Web server. The Web server, in turn, responds to the client by sending a response message and messages continue to be sent back and forth between the client and server to conduct the communications necessary to deliver an application. The messages that are sent between the client and the server contain simple text. If the messages used to conduct communications over the Web only contain text, how to more complex items such as images, graphs, animations, and multimedia get transported from a Web server to a client? The answer is that all items transported over the Web are first converted to text, then transported over the Web, then recreated from the text representation of the item. The process of converting a complex item to a text representation is call serialization.

To convert an item from a text representation back to the original object is called deserialization. The most common formats for an item to be converted to for transportation over the Web are XML, SOAP, and JSON. The .NET Framework on the server and that included in Silverlight both include facilities for serializing and deserializing data.

Accessing Data

Bear in mind that data stored in a database typically resides on a remote server while a Silverlight application resides on a client workstation. In order to retrieve data from a database stored on a remote server, requests must be sent to the server to retrieve the data just as with any other Web application. There are several methods for working with data in Silverlight as discussed below.

Isolated Storage

Due to the security constraints placed upon a Silverlight application (the "sandbox" that it operates in), a Silverlight application cannot read files from the client machine unless they are stored in isolated storage. Hence, a Silverlight application is fairly limited in its capability to store data locally, however simple files can be created for storing simple data and settings.

XML files can be deployed with a Silverlight application but must have their build action set to Embedded Resource so that when the application is built, the XML files are compiled into the assembly. This limits the ability to modify the file somewhat and limits the ability for the file to contain dynamic data that is shared with other users of the application.

Silverlight includes classes for working with XML, however these classes are designed for reading an incoming XML string (such as that coming from a call to a Web service) and not reading XML from a file.

Data Access By Using SOA

As discussed in an earlier module, a Silverlight application can make calls to a server by calling a Web service. Calls made to a Web service from a Silverlight application can currently transport data by using plain old XML (POX) or JSON. Additionally, a Web service being called by a Silverlight application must currently reside in the same domain as the Silverlight application. This restriction is imposed as a security precaution and limits the ability for the Silverlight application to make calls to Web services, however, it does not limit what a Web service being called by Silverlight can do. A Web service being called by Silverlight acts as a proxy for the Silverlight application and can make calls to any resource on behalf of the Silverlight application and return the results. For example, a Silverlight application may call a Web service that resides in the same domain as the application and that service may, in turn, call another Web service outside of the domain or may query a database. This is the standard method available for a Silverlight application to retrieve server resources.

The service that a Silverlight application calls may take the form of a standard ASP.NET Web service or a WCF service. As illustrated earlier, the ASP.NET Futures Web site project is designed exactly for the purpose of testing Web service calls from a Silverlight application. Once a new ASP.NET Futures Web site is created, a Web service can be added to the project and the service can be directed to transport data by using JSON. The following Web method is used to connect to a SQL Server database and return the results in an ArrayList. An ArrayList can be dynamically sized and is serializable. The most evident return value from a Web method that returns database results is an ADO.NET DataSet. However, does not currently support DataSets, hence an ArrayList will suffice.

Code Sample: AccessingDataUsingSilverlight/Demos/PetInformationService/App_Code/PetService.cs

using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using System.Web.Configuration;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;

/// <summary>
/// Summary description for PetService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class PetService : System.Web.Services.WebService {

    public PetService () {

        //Uncomment the following line if using designed components 
        //InitializeComponent(); 
    }

    [WebMethod]
    public List<string> GetPetInfo() {

      // Connect to the database.
      using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLExpress"].ConnectionString))
      {

        // Query the pet information.
        using (SqlCommand cmd = new SqlCommand("Select Name, Breed, Gender, Weight, Notes From Pets", cn))
        {

          cn.Open();
          List<string> petInfo = new List<string>();
          SqlDataReader rdr = cmd.ExecuteReader();

          while (rdr.Read())
          {

            petInfo.Add("My pet is named " + rdr["Name"].ToString() + ". It is a " + (rdr["Gender"].ToString() == "True" ? "male" : "female") + " " + rdr["Breed"].ToString() + " that weighs " + rdr["Weight"].ToString() + " pounds. " + rdr["Notes"] + " ");
          }

          rdr = null;
          return petInfo;
        }
      }
    }   
}

Next, the Silverlight application can be added to the same project as the Web service that will be called. This ensures that both the Silverlight application and the Web service reside in the same domain and are easily testable by using Visual Studio 2008. The following figure illustrates a Silverlight XAML file designed to consume pet information from the Web method above and display it in a TextBlock.

A Web reference can be added to the Silverlight application to reference the Web service. Once this is complete, the Get Pet Information region can be clicked to fire an event handler that calls the Web service and displays the results in the TextBlock. The following XAML listing is used to generate the page shown above.

Code Sample: AccessingDataUsingSilverlight/Demos/PetInformationClient/Page.xaml

<Canvas
        xmlns="http://schemas.microsoft.com/client/2007" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        x:Name="parentCanvas" 
        Loaded="Page_Loaded" 
        x:Class="PetInformationClient.Page;assembly=ClientBin/PetInformationClient.dll"
        Width="560"
        Height="320"
        >

 <Canvas.Background>
  <LinearGradientBrush EndPoint="0.498,-0.375" StartPoint="0.502,1.375">
   <GradientStop Color="#FFFFFFFF" Offset="0"/>
   <GradientStop Color="#FFA3A535" Offset="1"/>
  </LinearGradientBrush>
 </Canvas.Background>
 <Path Width="513" Height="1" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000" StrokeThickness="0.5" Canvas.Left="23.5" Canvas.Top="39.5" Data="M24,40 L536,40"/>

 <TextBlock Width="512" Height="232" Canvas.Left="24" Canvas.Top="56" TextWrapping="Wrap"><Run FontFamily="Segoe UI" FontSize="12" FontWeight="Normal" x:Name="tbOutput"/></TextBlock>
 <Canvas Cursor="Hand" Width="178" Height="24.5" Canvas.Left="23.5" Canvas.Top="11.5" x:Name="canvasGetPetInfo" MouseLeftButtonUp="GetPetInfo">
  <Rectangle Width="168.5" Height="24" Stroke="#FFD4A524" StrokeThickness="1" RadiusX="4" RadiusY="4">
   <Rectangle.Fill>
    <LinearGradientBrush EndPoint="0.505,4.01" StartPoint="0.495,-3.01">
     <GradientStop Color="#FF000000" Offset="0.301"/>
     <GradientStop Color="#00FFFFFF" Offset="0.737"/>
    </LinearGradientBrush>
   </Rectangle.Fill>
  </Rectangle>
  <TextBlock Width="168.5" Height="24" TextWrapping="Wrap" Canvas.Left="9.5" Canvas.Top="0.5"><Run FontFamily="Segoe UI" FontSize="16" Text="Get Pet Information"/></TextBlock>
 </Canvas>

</Canvas>

Finally, the event handler for the canvas that calls the Web service is shown in the code snippet below.

Code Sample: AccessingDataUsingSilverlight/Demos/PetInformationClient/Page.xaml.cs

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace PetInformationClient
{
  public partial class Page : Canvas
  {
    public void Page_Loaded(object o, EventArgs e)
    {
      // Required to initialize variables
      InitializeComponent();
    }

    public void GetPetInfo(object o, MouseEventArgs e)
    {

      PetInformationClient.localhost.PetService svc = new PetInformationClient.localhost.PetService();
      string[] petInfo = svc.GetPetInfo();

      // Display the results.
      for (int i = 0; i < petInfo.Length; i++)
      {

        tbOutput.Text += petInfo[i].ToString();
      }
    }
  }
}

The next step to test the Web service call from the Silverlight application is to add the Silverlight link to the ASP.NET Futures project and then add the asp:Xaml element to the Default.aspx test page. Press F5 and test the application. The resulting Silverlight application resembles the following figure.

As mentioned above, this illustrates a Silverlight application calling a Web service to retrieve data from a database. The Silverlight application could just as easily collect data and insert, update, or delete data in the database. The Web service being called could also perform any valid Web service action including calling other Web services in other domains.

Language Integrated Query (LINQ)

A major addition to the .NET Framework in version 3.5 is Language Integrated Query (LINQ). Most seasoned developers have mastered or are adequately familiar with the Structured Query Language (SQL). SQL is used to query relational database data. However, in many cases, SQL queries that pull data from a relational database schema are abstracted away from business logic and middle-tier code. Furthermore, data is generally represented at the business logic and code level through objects, arrays, and collections. Developers regularly have to search these constructs by using tailor-made loops.

Many programmers have long requested a language for querying data stored in programming constructs and object oriented mechanisms. SQL is a stable and well-entrenched industry standard. It would be an insurmountable task to attempt to extend SQL so that it could be used to query programming constructs. However, Microsoft was determined to make things easier for programmers by creating a standard for querying data stored in coding constructs. The result of their efforts was a new query language that targets data stored in objects and collections, Language Integrated Query (LINQ). LINQ was also extended to be able to query relational data stored in databases, XML data, and other data sources. However, data queried by using LINQ must be stored as objects. If data is queried from a relational data source using LINQ, it must first be represented using an object model.

LINQ is capable of querying any object programmatically that implements the IEnumerable interface. LINQ will present an entirely new programming paradigm to experienced .NET developers but the new functionality and benefits thereof should be quickly enjoyed and adapted by most.

As an example of implementing LINQ, we'll create the same example used above but utilize LINQ in the Web service to access data stored in SQL Server 2005 as well as in the code behind in the Silverlight application to iterate through the results.

The first step in creating a version of the Web service that utilizes LINQ to access data stored in SQL Server 2005 is to create a new ASP.NET Futures Web site, add a new Web service to the project, and then add a new LINQ to SQL Class to the project as shown in the following figure. The LINQ to SQL Class object has a .dbml extension (database modeling language).

Once a LINQ to SQL class is added, create data classes by dragging tables from the Server Explorer to the class design area. The figure below shows the class with the Pets table added to it.

The simplified version of the Web method that utilizes LINQ to retrieve the pet information from SQL Serve 2005 is shown in the following code snippet.

Code Sample: AccessingDataUsingSilverlight/Demos/PetInformationServiceLINQ/App_Code/PetService.cs

using System;
using System.Collections;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.Collections.Generic;

/// <summary>
/// Summary description for PetService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class PetService : System.Web.Services.WebService {

    public PetService () {

        //Uncomment the following line if using designed components 
        //InitializeComponent(); 
    }

    [WebMethod]
    public List<string> GetPetInfo()
    {

      List<string> petInfo = new List<string>();
      PetClassesDataContext petsDB = new PetClassesDataContext();

      var pets = from pet in petsDB.Pets
                 select pet;

      foreach (var pet in pets)
      {

        petInfo.Add("My pet is named " + pet.Name + ". It is a " + (pet.Gender == true ? "male" : "female") + " " + pet.Breed + " that weighs " + pet.Weight + " pounds. " + pet.Notes + " ");
      }

      return petInfo;
    }
}

The new code now utilizes the DataContext class created from the LINQ to SQL Class template and exposes the database to our code. The extreme benefit here is that developers will no longer have to master SQL and database languages but can now query and manage data stored in databases in the same manner as data stored in any type of programmatic collection. The code above is also more compact. The second line of the code is a query that correlates to a "Select * From Pets" SQL query where each item retrieved correlates to a row in the source database.

Not only can the Web service that resides on the server benefit from utilizing LINQ but the Silverlight application can also benefit. The event handler in the code behind in the Silverlight application that makes the call to the Web method is shown below after being converted to LINQ.

Code Sample: AccessingDataUsingSilverlight/Demos/PetInformationClientLINQ/PISCLINQ/Page.xaml.cs

using System;
using System.Linq;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace PISCLINQ
{
  public partial class Page : Canvas
  {
    public void Page_Loaded(object o, EventArgs e)
    {
      // Required to initialize variables
      InitializeComponent();
    }

    public void GetPetInfo(object o, MouseEventArgs e)
    {

      PISCLINQ.localhost.PetService svc = new PISCLINQ.localhost.PetService();
      IEnumerable<string> pets = from petInfo in svc.GetPetInfo()
                                select petInfo;

      // Display the results.
      foreach (string pet in pets)
      {

        tbOutput.Text += pet;
      }
    }
  }
}

It should be immediately evident that the LINQ code is much more compact and intuitive. The resulting Silverlight page is exactly the same using the LINQ versions as the non-LINQ versions.

Lab: Accessing Data Using Silverlight

In this lab, you will access data from a Silverlight application by calling a Web service. The code written in this lab should utilize LINQ and the end result will be a simulated weather forecast Silverlight control.

Accessing Data Using Silverlight Conclusion

In this lesson of the Silverlight tutorial, you

  • Reviewed data serialization
  • Retrieved data stored on a Web server by calling a Web service
  • Managed data by using LINQ
To continue to learn Silverlight go to the top of this page and click on the next lesson in this Silverlight Tutorial's Table of Contents.

Use of this website implies agreement to the following:

Copyright Information

All pages and graphics on this Web site are the property of Webucator, Inc. unless otherwise specified.

None of the content on this website may be redistributed or reproduced in any way, shape, or form without written permission from Webucator, Inc.

No Printing or saving of web pages

This content may not be printed or saved. It is for online use only.


Linking to this website

You may link to any of the pages on this website; however, you may not include the content in a frame or iframe without written permission from Webucator, Inc.


Warranties

This website is provided without warranty of any kind. There are no guarantees that use of the site will not be subject to interruptions. All direct or indirect risk related to use of the site is borne entirely by the user. All code and explanations provided on this site are provided without warranties to correctness, performance, fitness, merchantability, and/or any other warranty (whether expressed or implied).

For individual private use only

You agree not to use this online manual to deliver or receive training. If you are delivering or attending a class that is making use of this online manual, you are in violation of our terms of service. Please report any abuse to courseware@webucator.com. If you would like to deliver or receive training using this manual, please fill out the form at http://www.webucator.com/Contact.cfm.