Channels ▼
RSS

Web Development

What's New With Silverlight


Calling WCF RIA Services Operations From Silverlight

Once a domain service class is created it can be called from a Silverlight application without having to go through the process of generating a client-side proxy object using Add Service Reference. This is possible by the link between the Silverlight project and the Web project. After compiling the solution the Silverlight project will have a new folder added into it named Generated_Code (you'll need to click the Show All Files icon at the top of the Solution Explorer to see this folder). The code within the Generated_Code folder is automatically created during the build process and can be used to call the service. When the server-side code changes you don't have to update any service reference code like you would with a WCF service proxy.

To call a WCF RIA Services operation, a client-side domain context class can be used that will be named after the domain service class that lives on the server-side. This client-side class is automatically generated and added to the Generated_Code folder mentioned earlier. If the server-side class is named NorthwindDomainService then the client-side domain context class will be named NorthwindDomainContext by default. The domain context class can be used directly in the Silverlight code-beside file or can be integrated into a ViewModel class in cases where the Model-View-ViewModel (MVVM) pattern is being used (see my blog post if you're interested in getting started with the MVVM pattern).

Listing 3 is an example of using the domain context class within a ViewModel class named CustomersViewModel to call the WCF RIA Service and assign data returned from the service to Customers and Orders properties.


using System.Linq;
using System.Windows.Ria;
using StarterSample.Web;

namespace StarterSample.ViewModel
{
    public class CustomersViewModel : ViewModelBase
    {
        EntitySet<Customer> _Customers;
        EntitySet<Order> _Orders;
        Order _CurrentOrder;
        NorthwindDomainContext _Context = null;

        public CustomersViewModel()
        {
            _Context = new NorthwindDomainContext();
            this.Customers = _Context.Customers;
            this.Orders = _Context.Orders;
            GetCustomers();
        }

        #region Properties

        public Order CurrentOrder
        {
            get
            {
                return _CurrentOrder;
            }
            set
            {
                if (_CurrentOrder != value)
                {
                    _CurrentOrder = value;
                    OnPropertyChanged("CurrentOrder");
                }
            }
        }

        public EntitySet<Customer> Customers
        {
            get
            {
                return _Customers;
            }
            set
            {
                if (_Customers != value)
                {
                    _Customers = value;
                    OnPropertyChanged("Customers");
                }
            }
        }

        public EntitySet<Order> Orders
        {
            get
            {
                return _Orders;
            }
            set
            {
                if (_Orders != value)
                {
                    _Orders = value;
                    OnPropertyChanged("Orders");
                }
            }
        }

        #endregion

        private void GetCustomers()
        {
            _Context.Load<Customer>(_Context.GetCustomersQuery());
        }

        public void GetOrders(string custID)
        {
            _Context.Orders.Clear();
            _Context.Load<Order>(_Context.GetOrdersQuery(custID), lo =>
                {
                    if (lo.TotalEntityCount > 0)
                    {
                        this.CurrentOrder = 
                         this.Orders.Take(1).SingleOrDefault();
                    }
                }, null);
        }

        public void UpdateOrder()
        {
            _Context.SubmitChanges();
        }
    }
}

Listing 3

Looking through the code you'll see that the Customers and Orders collection properties store an EntitySet<T> type as opposed to ObservableCollection<T>. EntitySet<T> is provided by WCF RIA Services and used to track changes that are made to objects as discussed later in the article. You'll also see that as the CustomersViewModel object's constructor is called an instance of the domain context class is created and used to access Customer and Order entities exposed by the service and assign them to the CustomersViewModel properties.

Once the entities are assigned a call is made to GetCustomers which invokes the domain context object's Load<T> method. The type of query to load is passed into the method (GetCustomersQuery in this example which is automatically generated based upon the service query named GetCustomers; see Listing 1). Although the call to Load<T> looks synchronous it's actually asynchronous behind the scenes. As data is returned from the service it will be assigned to the CustomersViewModel object's Customers property due to the association created in the constructor.

As a customer is selected in the Silverlight interface (see Figure 5) the GetOrders method in Listing 3 is called which handles loading all of the orders for the customer by calling Load<Order> and passing in the GetOrdersQuery that's automatically generated when the solution is compiled. Once the orders are returned back to the Silverlight client an inline callback method is invoked within the GetOrders method which accepts a LoadOptionsj parameter. LoadOptions provides a way to check for errors and access entities that were returned from the service. In this example a check is made to see if the LoadOptions object's TotalEntityCount property is greater than 0. If that condition is met the first order is assigned to the CustomersViewModel object's CurrentOrder property which displays in the DataFormcontrol shown to the end user (see Figure 5).

Figure 5: The Silverlight interface gets its data from WCF RIA Services.

The DataForm allows order data to be edited by the end user. In a typical Silverlight application that uses WCF or ASMX services, code would have to be written to track object changes and then send them back to a custom service operation. WCF RIA Services simplifies this process by tracking all objects defined in an EntitySet. As changes are made the data context object's SubmitChanges method can be called to send all changes back to the server for processing. An example of using SubmitChanges is shown next:


public void UpdateOrder()
{
    _Context.SubmitChanges();
}

The appropriate Insert, Update or Delete methods defined in the domain service will be called after SubmitChanges is called in the Silverlight application. The sample application available here demonstrates other features such as the ability to access a customer's orders and edit the data using a DataForm control.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 
Dr. Dobb's TV