OpenLightGroup Blog

rss

Blogs from OpenLightGroup.net


Simple Silverlight 4 Example Using oData and RX Extensions

This is part II to the previous Blog (http://openlightgroup.net/Blog/tabid/58/EntryId/98/OData-Simplified.aspx) where we looked a simple OData example. This time we will make a simple Silverlight application that talks to an oData service.

Note, for this tutorial, you will also need to download and install RX Extensions from: http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx, and the Silverlight Toolkit from: http://silverlight.codeplex.com.

As with the last tutorial, we will not use a database, just a simple collection that we are creating programmatically. This will allow you to see just the oData parts.

First, open up the project, in Visual Studio 2010 (or higher), from the zip file at the bottom of this link.

Select Add then New Project...

Create a new Silverlight Application.

Add a Service Reference.

Click Discover.

Create a reference called wsSampleCustomerData.

Next, add assembly references in your Silverlight project to:

  • System.CoreEx
  • System.Observable
  • System.Reactive

In the Silverlight project, delete the MainPage.xaml

Open the project in Expression Blend 4 (or higher).

In Expression Blend, Select File then New Item...

Select the UserControl with ViewModel template, and create a file called MainPage.xaml.

It will create the ViewModel pages (MainPage.xaml and MainPage.xaml.cs with a MainPageModel.cs View Model page that is already wired-up).

Create a folder called Model and a class called Model.cs.

Replace all the code with the following code:

using System;
using System.Linq;
using System.Collections.Generic;
using SilverlightODataSample.wsSampleCustomerData;
using System.Data.Services.Client;
namespace SilverlightODataSample
{
    public class Model
    {
        #region GetCustomers
        public static IObservable<IEvent<LoadCompletedEventArgs>> 
            GetCustomers(int intPage)
        {
            // Create a URI that points to the OData Service
            Uri objUri = new Uri(GetBaseAddress(), UriKind.RelativeOrAbsolute);
            // Set up oData service call
            SampleDataSource SDS = new SampleDataSource(objUri);
            // Construct a Query
            var query = (from SampleCustomerData in SDS.SampleCustomerData
                         where SampleCustomerData.CustomerNotes.Contains("3")
                         select SampleCustomerData).Skip(intPage).Take(10);
            // Set up a DataServiceCollection to hold the results
            DataServiceCollection<CustomerRecord> CustomerRecords = 
                new DataServiceCollection<CustomerRecord>();
            // Set up a Rx Observable (in a variable called observable) 
            // that will contain the results of
            // the "LoadCompleted" event that CustomerRecords will fire
            // When LoadAsync(query) is fired in the following stetement
            IObservable<IEvent<LoadCompletedEventArgs>> observable =
                Observable.FromEvent<LoadCompletedEventArgs>(CustomerRecords,
                "LoadCompleted");
            // Execute the LoadAsync on CustomerRecords passing
            // the query that was constructed earlier
            CustomerRecords.LoadAsync(query);
            // Return observable
            return observable;
        }
        #endregion
        #region GetBaseAddress
        private static string GetBaseAddress()
        {
            // This gets the address of the webservice by 
            // getting the AbsoluteUri and then stripping out the 
            // name of the .xap file
            string strXapFile = @"/ClientBin/SilverlightODataSample.xap";
            string strBaseWebAddress =
                App.Current.Host.Source.AbsoluteUri.Replace(strXapFile, "");
            return string.Format(@"{0}/{1}", strBaseWebAddress, @"Service.svc");
        }
        #endregion
    }
}
 

Open MainPageModel.cs and replace all the code with the following code:

using System;
using System.ComponentModel;
using System.Collections.ObjectModel;
using SilverlightODataSample.wsSampleCustomerData;
using System.Data.Services.Client;
namespace SilverlightODataSample
{
    public class MainPageModel : INotifyPropertyChanged
    {
        public MainPageModel()
        {
            // When the Control loads
            // Get the Customers
            GetCustomers();
        }
        #region GetCustomers
        private void GetCustomers()
        {
            // Call the Model to get the Customers
            // Passing in 0 to get the first page
            // Paging could easily be done here
            // You could also pass in other criteria
            Model.GetCustomers(0).Subscribe(p =>
            {
                // Check for an error in the Service
                if (p.EventArgs.Error == null)
                {
                    // loop thru each item in the
                    // DataServiceCollection<CustomerRecord>
                    // Collection
                    foreach (CustomerRecord Customer in
                        (DataServiceCollection<CustomerRecord>)p.Sender)
                    {
                        // Add to the Customer to the colCustomerRecord 
                        // Collection so the View can bind to it
                        colCustomerRecord.Add(Customer);
                    }
                }
            });
        }
        #endregion
        #region CustomerRecord
        // The View will bind to this collection and automatically be notified if 
        // The collection changes. The Designer can bind any UI element that 
        // can hold a collection
        private ObservableCollection<CustomerRecord> _colCustomerRecord
            = new ObservableCollection<CustomerRecord>();
        public ObservableCollection<CustomerRecord> colCustomerRecord
        {
            get { return _colCustomerRecord; }
            private set
            {
                if (colCustomerRecord == value)
                {
                    return;
                }
                _colCustomerRecord = value;
                this.NotifyPropertyChanged("colCustomerRecord");
            }
        }
        #endregion
        #region INotifyPropertyChanged
        // This is a supporting method to raise a notification for any
        // Element that is subscribed to a Property that implements
        // NotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }
}

 

 

Grab a DataGrid and drop it on the design surface.

Widen it so it fills the page.

Click on the Data tab so that you see the Data Context.

Drag and drop colCustomerRecord collection onto the DataGrid.

Build and run the project.

OData and RX extensions are pretty impressive:

  • RX extensions were used because it decouples the oData Service calls from the View Model. This allows the methods in the model to be easily called by multiple View Models.
  • We are only grabbing the first page of the results but we could easily implement paging by passing the page number to the method
  • We are also only creating a simple query. We could easily create a more complex query of the oData Service

Download the Code

Download the Code here: ODataSample.zip

Further Reading

http://www.leastprivilege.com/ThinktectureIdentityModelWIFSupportForWCFRESTServicesAndOData.aspx





Comments are closed.
Showing 8 Comments
Avatar  Michael Washington 7 years ago

@Robert Hellestrae - I looked at would be required to do an update and I have came to the conclusion that it would be easier to just use WCF RIA Services for that.

Avatar  Robert Hellestrae 7 years ago

I'm writing to inquire if there is any sample code for updating / inserting records, much like the below sample code from the demonstrations. Best regards, Rob &lt;br&gt;&lt;br&gt;// Construct a Query&lt;br&gt; var query = (from SampleCustomerData in SDS.SampleCustomerData&lt;br&gt; where SampleCustomerData.CustomerNotes.Contains(&quot;3&quot;)&lt;br&gt; select SampleCustomerData).Skip(intPage).Take(10);&lt;br&gt;

Avatar  Michael Washington 7 years ago

@Robert Hellestrae - Silverlight should have no difficulty connecting to an existing service. The fact that the service is connected to SQL Server should not make a difference.

Avatar  Robert Hellestrae 7 years ago

I have scenario where an end point is already created - I'm writing to ask if you may know how to work from Silverlight client to a service that is configured to connect with an SQL Server database. Best regards, Rob

Avatar  Michael Washington 7 years ago

@Gavin - I am glad you found it useful. Thanks for taking the time to leave a comment.

Avatar  Gavin 7 years ago

Great example. Have been looking for a concrete example of using RX with WCF Data Services and DataServiceCollection. Found it has taken a re-think in getting my head around the RX syntax but this was just the ticket. Thanks very much.

Avatar  Michael Washington 7 years ago

@Robert Hellestrae - Thank you for the feedback. I appreciate it.

Avatar  Robert Hellestrae 7 years ago

Excellent walkthrough on OData and RX extensions with Silverlight 4! Best regards, Rob