End-to-End Data Centric Application with Silverlight 2


I have been having some fun with an end to end Silverlight 2 demo recently and I thought I’d share it here.   My goal with the demo is to show how easy it is to create an end to end Silverlight application.  In particular, my goal is to show

  1. Explain the Silverlight Project Format
  2. How to do rich layout and animation
  3. Uses line of business controls for Silverlight such as DataGrid
  4. Has a Linq based data layer on the server on the server
  5. Exposes business logic over that data via a WCF web service
  6. Consume the service on the client in Silverlight and databind to the DataGrid
  7. Store result locally to minimize round trips to the server across instantiations with IsolatedStorage
  8. Re-theme the UI to make it look more cool.
  9. Do it all in code that you could easily write on stage in about 30-45 mins
  10. Have Fun!

 

Download the completed sample (VB one is available as well)

 

Here is a screen show of what we are going to end up with..

image

 

I. Create the Silverlight Project

In VS2008 with the Silverlight 2 Tools for Silverlight installed, create a new Silverlight application

image

 

image

VS asks you to create a home web site for your Silverlight application.  This is important because we are going to implement our data access layer and web services layer in this web site. 

What VS creates for you looks like:

image

The web project contains an ASP.NET page that gives you already wired up to the Silverlight application.    Notice we use the new ASP.NET Silverlight control here to host rich silverlight content within your ASP.NET page. 

        <asp:Silverlight ID="Xaml1" runat="server" 
            Source="~/ClientBin/EndToEndSilverlightDemo.xap"
            Version="2.0" Width="100%" Height="100%" />

There is also a plain-old HTML page that you can host on any web server (Apache, etc)..  Nothing in Silverlight requires ASP.NET or even IIS on the server.

Notice the EndToEndSilverlightDemo.xap file?  This is the client side silverlight application.  The .xap file is just a zip file format.  So in fact if you just rename it to .zip, you can easily see inside. 

image

image

What we see here is the Manifest for the Silverlight application, the actual C# or VB code you write for the application and then the parts of the framework your application needs.  By Silverlight RTM, many of controls will be rolled into the core so you don’t have to include them in your application.

 

 

II. Rich Layout

Let’s start with some very basic Silverlight coding.  In page.xaml, let’s start easy and just add a button.

image

Now, that button defaults to filling the entire grid, so let’s give it a size, and some text…

image

As an aside, it is interesting to note that the property label on the button is called “Content” rather than “Text” or something like that.. the reason is because you can in fact have anything in a the button… for example a couple of images, a video, or even, well, another button!

image

Not sure why you would want to do that, but it is good to know you can!

let’s leave the Xaml to look like this:

        <Button x:Name="btnOne" Width="100" Height="50" 
                Content="Push Me!"
                Click="Button_Click">
        </Button>

 

OK, enough playing around.. this is Silverlight 2, it is all about .NET code, so let’s show a little of that.   Let’s add a simple event handler and write some code. 

Notice how VS makes it so easy to add an event handler

image

And VS also makes it very easy for me to navigate to that event handler

image

 

In the event handler, notice I get strongly typed access to the button I just defined in Xaml.  I can also set a break point..

image

Now, hit F5 and run the solution.. notice what is happening:  the code you just typed is being compiled into a .dll, that dll is being zip’ed up in the .XAP file for deployment with any of its dependences.  It is being copied up to the server project, the ASP.NET page is being loaded, it loads the silverlight player in the browser which downloads .XAP file unzips it loads the Xaml and executes our C# code!

That is a lot for a little button!

image

Notice how clicking on it changes the next and hits our break point!  All the power of VS right here in your Silverlight application.

image

Ok, that is cool, but how about some of that richness…  Let’s talk a little bit about the developer\designer collaboration in VS\Expression. 

Notice on my Xaml file, I can right click and Open in Expression Blend

image

This is where we move into design mode and actually build some cool UI…

In Blend, select the Layout Root and give it a nice gradient fill. 

image

(you can tell I am not really a designer…)

Now, let’s do a little animation, to do that, add a new Story Board

image

Now simply change any properties of the button, move it around the screen to define the animations you want to happen and the different times

image

 

Save the changes, and why you pop back to VS, it tells you the Xaml has been changed… This is way better than passing bitmaps around between developers and designers.

image

Then we go back into our click event and start that story board

 

private void Button_Click(object sender, RoutedEventArgs e)
{
    btnOne.Content = "I've been pushed!";
    Storyboard1.Begin();
}

For a fun little Silverlight version of the moving button game, add an event handler for mouse enter and play the story board from there

      <Button x:Name="btnOne" Width="100" Height="50" 
                Content="Push Me!"
                Click="Button_Click"
                MouseEnter="btnOne_MouseEnter"
                RenderTransformOrigin="0.5,0.5">

 

private void btnOne_MouseEnter(object sender, MouseEventArgs e)
{
    Storyboard1.Begin();
}

 

Ok… that was fun, but let’s go back into Blend now and define a little more sensible UI..

Notice the snap lines and layout help?

image

And how easy it is to define a grid layout and get docking and resize to work correctly

image

 

Now to work around a little bug in Expression, we need to add a reference to the System.Windows.Controls.Data.dll assembly where the DataGrid control lives.   You do that under Project\Add Reference.  It should be in the “C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Libraries\Client” directory.

image

 

Now from the asset library it is easy to find DataGrid

image

image

 

 

III.  Defining the Data Layer

Ok, that is all fun UI stuff, but now let’s get down to it.   Let’s go back to the server project and add a data layer. 

First, just to get access to the database, I add northwind.mdf to the app_data director

 

Then, right click, add new item and select Ling to Sql Classes.  Notice that EF or NHibranate or whatever would work in the same way.

image

 

Then, in the Linq designer add the Products table from Northwind

image

Now, we need to make sure that the Linq model is created in a way that we can expose it over a web service.  So I need to change the Serialization Mode to Unidirectional

image

Clearly if this were more real world, at this point I would add data validation and business logic. 

 

 

IV. Define the Services Layer

I’ll show creating a services layer with WCF. 

Right click, add new Item and select WCF Service

image

 

Open the services interface and define the right contract

[ServiceContract]
public interface INorthwindService
{
    [OperationContract]
    List<Product> GetProducts(string productNamePrefix);
}

 

Then open the concrete implementing and click on the smart tag on the interface and implement the interface

image

This creates the following code

public class NorthwindService : INorthwindService
{
    public List<Product> GetProducts(string productNamePrefix)
    {
        throw new NotImplementedException();
    }

}

Now I need to create the implementation  of this method which is simple with Linq.

public List<Product> GetProducts(string productNamePrefix)
{
    NorthWindDataContext db = new NorthWindDataContext();
    var q = from p in db.Products
            where p.ProductName.StartsWith(productNamePrefix)
            select p;
    return q.List();
}
 

The final step here is to change the WCF binding to httpBasic as that is what the current Silverlight client supports. In web.config change wsHttpBinding to basicHttpBinding

image

The new web.config changes are:

<endpoint address="" binding="basicHttpBinding" 

 

IV. Consume the Service in the Silverlight client

Now we need to consume the service from the Silverlight client. 

The first step is to add Service reference to the client project

image

 

Click “Discover”

image

 

Now, let’s make sure our Textbox and DataGrid are accessible from C# code by setting their x:Name and while we are there, let’s set the AutoGenerateColumns on DataGrid to true. 

image

 

Now, in the code behind for page.xaml, do three things:

1. Create the NorthwindServiceClient class that is the holder for the service calls
2. All network call in Silverlight are aync to keep the browser from hanging, so we need to setup a callback, notice that VS does a lot of this for you.
3. Make the async call. 

private void Button_Click(object sender, RoutedEventArgs e)
{
    var client = new NorthwindServiceClient();
    client.GetProductsCompleted += 
        new EventHandler<GetProductsCompletedEventArgs>(client_GetProductsCompleted);
    client.GetProductsAsync(txtProductString.Text);
}

 

Then the completed callback is simple!  just set the datagrid’s ItemSource to the events Results

void client_GetProductsCompleted(object sender, GetProductsCompletedEventArgs e)
{
    dataGridResults.ItemsSource = e.Result;
}

Run it, enter some prefix hit submit and see the results!  Yea!

image

 

Ok, that is cool, but let’s see if we can leverage some of the local storage capability of Silverlight.  For example, let’s cache the result so that whenever the application is loaded we show the results of the last call with no network hit.

To do this, in page.xaml.cs add an import for IsolatedStorage

using System.IO.IsolatedStorage;
 

Create the settings instances in the page class

public partial class Page : UserControl
{
    ApplicationSettings settings = ApplicationSettings.Default;

 

then simply save the results in the property store

void client_GetProductsCompleted(object sender, GetProductsCompletedEventArgs e)
{
    dataGridResults.ItemsSource = e.Result;
    settings["defaultDataGridValue"] = e.Result;
    settings.Save();
}

and reload them, if they are there on the page load.

public Page()
{            
    InitializeComponent();
    if (!settings.Contains("defaultDataGridValue"))
    {
        settings.Add("defaultDataGridValue", null);
    }
    else
    {
        dataGridResults.ItemsSource = settings["defaultDataGridValue"] as Product[];
    }
}

Now notice the first time you run it, nothing is in the datagrid.  But do you search, the result display, then close the browser and re-run… the last search results will be displayed.  Now open it in FireFox, again the results are there.

 

 

V. Sex up the UI a bit

Now, let’s see if you can make the UI even cooler.  Let’s do that by skinning all the controls.  Corrina has created some great skins, let’s see about applying one.

To do that, grab the Application.Resources section out of app.xaml file in corrina’s Rough sample and copy it this applications app.xaml file.  You’ll also need to add the data namespace to app.xaml

xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

 

Then, we need to reference these styles from the page.xaml.

        <Button Style="{StaticResource buttonStyle}"

        <TextBox Style="{StaticResource textBoxStyle}" 
        <System_Windows_Controls:DataGrid Style="{StaticResource dataGridStyle}"

 

Then you run it and it looks great!

image

 

Download the completed sample

I’d love to hear your feedback\thoughts. 

Comments (27)

  1. You’ve been kicked (a good thing) – Trackback from DotNetKicks.com

  2. Adrian says:

    Good tutorial, I´d like to the see the hairy part (e.g. change data, and updating it on the server) too..would that be possible?

  3. Interesting tutorial. I hope that the tools will be better in RTM as there is way too much Xml to type.

  4. Eric Hexter says:

    The Silverlight testing framework was recently released and shows some great potential for being a first

  5. David Fauber says:

    The ClientBin folder is not created for me when I create the solution (and thus, neither is the EndToEndSilverlightDemo.xap file, which leads to errors in the designer).  Any idea what I’m doing wrong?

  6. BradA says:

    Adrian asks about showing the "harder" parts of a data centeric application such as updating the data.  That is a great ask, I will look into it for my next pots.

    Pawel points out there is lots of Xaml editing here..  I am doing that to show what is really happening.. you can do 100% of the Xaml editing I show here in Expression Blend in design time.   And, yes VS is getting better and better the Xaml design surface.

    David Fauber isn’t seeing the ClientBin folder created in the server project.  I think this could be becaus you have not done a full build of the solution yet.  

  7. Martin says:

    Hi,

    How can the data grid be populated without linq, i have data constructs that are constructed through business logic and not just from a simple select statement from the database. I’ve tried just creating a simple class with a single public string variable set with a value and then push an array of those to the ItemsSources property with no joy.

    What is the proper way to pass arbitary data to this grid?

  8. I have been having some fun with an end to end

  9. Menezes says:

    Very good Tutorial Brad Abrams.

    Very Interesting !

  10. BradA says:

    Martin asks about Databinding to .NET Objects rather than LINQ…  Scott covers that in his blog post here:

    http://blogs.msdn.com/scmorris/archive/2008/03/21/using-the-silverlight-datagrid.aspx

    One thing you need to be sure of is that you use public properites rather than fields…

  11. Jesse says:

    Very informative post, and I’m glad to see that you covered the basic httpBinding issue with WCF, as that was a stumbling block for me when I tried to build a simple data-driven app in Silverlight for a demo recently. I’m giving a similar demo at a user group meeting again in a couple of months and will look to incorporate use of IsolatedStorage for ‘caching’ as you’ve done here. I found your previous posts to this very helpful in putting my own demos together, thanks!

  12. Mark Bennett says:

    Wow, great tutorial.  I just wrote one very similair to this and yours puts mine to shame!  I especially like the part which covers database access.

  13. Rudi says:

    Like Adrian, I’d also like to see the harder parts:

    – edit a row

    – implement a little business logic

    – data validation (using the business logic)

    – relation to other tables (master-detail view)

    I know CSLA.NET should be a great fit for this, but what if I can’t use that, and am ‘stuck’ with only the MS provided bits.

    Can I use the Validation Block of EntLib?

    Can I use WF to hold UI workflow?

    Great start, many more posts to come?

  14. I’ve been OOF on vacation (Hawaii, where it’s warm!).&#160; But I’m back now and here’s a few new sample

  15. Blogs says:

    In this example I will demonstrate a very simple call to the FlickR REST APIs from a Silverlight client

  16. 李永京 says:

    Silverlight 2支持JSON、Web Service、WCF以及Sockets等新特性对数据CRUD操作,这个系列用实例结合数据库一步一步的图文描述来学习一下Silverlight 2 beta 1中进行数据库的CRUD操作方面的实战能力。

  17. 【原文地址】 Silverlight FlickR Example 【原文发表日期】 25 April 08 11:23 在这个示例中,我将示范在Silverlight客户端通过一个非常简单的调用去访问FlickR的REST

  18. Post: Approved at: Apr-30-2008 SL2 End-To-End Data Centric App example Brad Abrams posted a tutorial

  19. Bob's Blog says:

    Abstract This series of articles takes a look at the current state of RIA development leveraging Silverlight

  20. Calvin Guo says:

    Security.

    The end to end application is what I am targeting for now, but I see a big security hole for this model.

    Since we have to expose all discrete functionalities in web services, which means anybody can call those web services, as long as your silverlight application can.

    There’s no easy way to restrict those web services to be called only by your silverlight application, or you have build security inside the business layer. This is a big change to normal website applications. Most people build security into UI instead. i.e. Security drives UI, and you can only rich certain UI based on your credential, and then you can only performance certain functionalities in that UI. If we switch to Web Service approach,  we will have to define security for every webservice call. Which is a huge amount of work, consider you could have so many web services.

    Any idea?

  21. Alan Gramont says:

    There is an error on the text give for the GetProducts method.  The correct body of the method is:

    NorthWindDataContext db = new NorthWindDataContext();

           var q = from p in db.Products

                   where p.ProductName.StartsWith(productNamePrefix)

                   select p;

           return q.ToList();

  22. jr says:

    version of Silverlight tools, runtime, and sdk please…  is this Beta1?

  23. Programming says:

    In this example I will demonstrate a very simple call to the FlickR REST APIs from a Silverlight client

  24. BradA says:

    >> version of Silverlight tools, runtime, and sdk please…  is this Beta1?

    Jr – this is all beta1.. hopefully I or someone else will port to beta2

  25. David says:

    hello, this looks like a good tutorial but i have silverlight 2.0 beta and i downloaded the your sample code…but it gives me an error and it wouldn’t run.

  26. David says:

    and i forgot to add…that the Error message was

    The type or namespace name ‘ApplicationSettings’ could not be found (are you missing a using directive or an assembly reference?) C:Documents and Settingszz-dbchauMy DocumentsVisual Studio 2008ProjectsEndToEndSilverlightDemoEndToEndSilverlightDemoPage.xaml.cs 18