Silverlight 2 Beta 2 - Doing Data Part I

By Peter Bromberg

This is the first in a series of articles focusing on working with Data and Databinding with Silverlight 2 Beta 2. Each article in this series will focus on a simple "task" in an easy-to-understand progression of working with Data via ASMX and WCF web service, WebClient, and other modalities, and using Silverlight Controls.

The future is here. It's just not widely distributed yet.  - William Gibson

To start, I'll lay out some groundwork so you can understand how the article projects will be set up, and why. First, I do all my ASP.NET web projects as "Web Application Projects" running under IIS (not the built-in web dev server).  I do this because the WAP under IIS is the closest you can get to an actual deployed app in production. Many developers and authors use the Web Site model, and use SQLEXPRESS with User Instance connection strings that point to the MDF database file in the App_Data folder. While this arrangement is very handy, I have seen that it also causes a great deal of confusion with newer developers when they attempt to deploy these, as "real life" hosted IIS accounts don't play well at all with these arrangements. All my databases are full SQL Server databases that are attached; no User Instance connections are employed.

Each solution in this series will uses a subset of my Quotations database. This "stripped down" database has 1000 famous quotations arranged in three tables (my original has 44,000 quotations, a little too big for a sample download!):

The database also includes a series of stored procedures sufficient to build a complete "Quotations" web site or Silverlight app. The SQL Script to create this database is in the /SQL subfolder of the solution.  So first, you'll want to create a new SQL Server database named "QUOTES", and run the SQL Script to populate everything.

For our first solution, we will create an ASMX WebService with a GetRandomQuote WebMethod. The method will accept two parameters, an int "numberofquotes" to return, and an optional string subject that corresponds to the Subject column in the Subjects table. We will then create a Silverlight app that consumes this webservice and binds the returned data to a DataGrid.

Create a new ASP.NET Web Application. Now Add a  Web Service (ASMX) to it with "Add, New Item". Now lets create a Quotation class that will mirror and contain the data returned from the database:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

namespace SilverlightWeb
{
    [Serializable]
    public class Quotation
    {
        public string AuthorName { get; set; }
        public string Subject { get; set; }
        public string AuthorInfo { get; set; }
        public string Quote { get; set; }
        public Quotation(  string authorName,  string subject, string quote, string authorInfo)
        {
            this.AuthorName = authorName;
            this.Subject = subject;
            this.Quote = quote;
            this.AuthorInfo = authorInfo;
        }

        public Quotation()
        {
        }
    }
}
Now, lets set up the WebMethod to retrieve our data, populate a List of Quotation objects, and return it:
[WebMethod]
        public List GetRandomQuote(int numQuotes, string subject)
        {
            var cnString = ConfigurationManager.ConnectionStrings["quotes"].ConnectionString;
            SqlDataReader rdr = PAB.Data.Utils.SqlHelper.ExecuteReader(cnString,
               "dbo.GetRandomQuote", numQuotes,  subject);
            var quotes = new List();           

            while (rdr.Read())
            {                 
                var AuthorName = (string)rdr["AuthorFirstName"] + " " +(string)rdr["AuthorLastname"];
                var authorInfo = (string)rdr["AuthorInfo"];
                var theQuote = (string)rdr["quotation"];
                var subj = (string)rdr["Subject"];
                var quote = new Quotation(AuthorName,  subj, theQuote,authorInfo);
                quotes.Add(quote);
            }
            rdr.Close();
            return quotes;
        }

Note that I'm using the handy SqlHelper class here. In later articles, we'll be using the LINQ to SQL generators. But for now, let's just keep it simple in order to get to "First Base".

Your WebService is now complete. Of course, you can look at the stored procs in the database and add additional WebMethods later. Test your WebService by right-clicking on the Service1.asmx page and selecting "View in Browser". You should see the standard ASMX webservice discovery page listing our one method. We are now ready to create our Silverlight Consumer App.

Add a new Silverlight Application to your Solution and accept the offer to add the Silverlight Test page to your existing Web Application. I called my app "quoter".  Now let's add a Service Reference to our SL App. In Solution Explorer, under Service References, right-click and "Add Service Reference". You should be able to Discover the existing WebService in the solution and the ServiceReference1 will be added.

Now we will consume and display the results of the GetRandomQuote WebMethod in a Silverlight DataGrid. In your Page.xaml markup, add the following code inside the default Grid usercontrol:

<Controls:DataGrid x:Name="Grid1"  Width="900" AutoGenerateColumns="True" Margin="0,0,0,0"  >
</Controls:DataGrid>
Now in our Page.xaml.cs codebehind, here is how we can consume the results:
public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            var c = new WebService1SoapClient();
            c.GetRandomQuoteCompleted += new EventHandler(c_GetRandomQuoteCompleted);
            c.GetRandomQuoteAsync(2, "");
        }

        void c_GetRandomQuoteCompleted(object sender, GetRandomQuoteCompletedEventArgs e)
        {
            ObservableCollection q = e.Result;
            this.Grid1.ItemsSource = q;
        } 
    }

In the Page constructor, we create an instance of the WebServiceSoapClient proxy. Then we set the GetRandomQuoteCompleted callback (you can type "+=" and hit the Tab key to stub this out automatically). Then we call the method, passing in a 2 to get 2 random quotes, and a null string for the subject, meaning "any subject".

In the callback method, we are going to get an ObservableCollection from our Generic List in the WebMethod. If your DataGrid has AutoGenerateColumns set, you can bind this directly to the DataGrid's ItemsSource property, and you are done!

The display should look something like this:

Incidentally, this works great in Firefox 3 RC1 on my machines.  In the next installment of the series, we'll add a ListBox of the Subjects and a Button to retrieve the results, and we'll switch to a WCF Service to get our data, plus a couple of other nice surprises.

D00ds, I CAN HAS SILVERLIGHT is within your grasp! KTHXBYE!

You can download the complete Visual Studio 2008 Solution here. Don't forget to change the connection string in the web.config to match your environment!
See Part II of this series.
Popularity  (1332 Views)
Picture
Biography - Peter Bromberg
Peter Bromberg is a C# MVP, MCP, and .NET expert who has worked in banking, financial and telephony for over 20 years. Pete focuses exclusively on the .NET Platform, and currently develops SOA and other .NET applications for a Fortune 500 clientele. Peter enjoys producing digital photo collage with Maya,playing jazz flute, the beach, and fine wines. You can view Peter's UnBlog and IttyUrl sites. Follow Microsoft MVP
Create New Account
Article Discussion: Doing Data With Silverlight 2 Beta 2 - Part I
Peter Bromberg posted at Saturday, June 14, 2008 10:10 AM
reply
Exception when trying to open solution
Michael Mitiaguin replied to Peter Bromberg at Saturday, June 14, 2008 10:49 AM
Just uncompressed zip , ran sql script , replaced connection strings in web.config ( which is probably irrelevant for opening solution ). In VS 2008 it gives me the error message when I try to open the solution   
---------------------------
Microsoft Visual Studio
---------------------------
System.Runtime.InteropServices.COMException
---------------------------
OK   
---------------------------

web project is shown unavailable ( the project file cannot be loaded ). What should I look at to gather more info ?
reply
Do you have IIS installed?
Peter Bromberg replied to Michael Mitiaguin at Saturday, June 14, 2008 10:49 AM
If you do not, you'll need to adjust the web project csproj file to use the Visual Studio Development webserver.
reply
How i can pass data from webservice to SL2beta2
sajesh k replied to Peter Bromberg at Saturday, June 14, 2008 10:49 AM

Hi Peter,

Very good article.I have one doubt.In ur sample project u have one static class with name  qoutation with static feilds[eg:authorname,book name] .I mean feilds are same for whole case .

I need to change this feilds based on table we are selecting.Is there is any way to do this?

eg: Table 1 with feilds Account No,Customer Name,Date

     Table 2 with feilds Account no,Account Type,Branch

How i can design property procedure for this?

Thanks in advance

Regards,

Sajesh

reply
Based on my understanding of what you need,
Peter Bromberg replied to sajesh k at Saturday, June 14, 2008 10:49 AM
you would need to create a separate class to map with the fields of each of your two tables. Of course if there is a one-to-many relationship between the tables, it would be possible to design a parent class that has a collection field containing one or more instances of a child class.
reply