Accessing Data Using Silverlight
- About how data is serialized when transported over the Web
- To access data stored on a Web server by calling a Web service or WCF service
- 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
