A Simple approach to build a Silverlight 3.0/Silverlight 4.0 application that consumes a WCF Service

Posted by: Mahesh Sabnis , on 5/3/2010, in Category Silverlight 2, 3, 4 and 5
Views: 27994
Abstract: Silverlight is now used for developing LOB applications where the requirement is to develop loosely coupled browser based applications using Silverlight. One of the approaches here is to remove the dependency between Model and View like MVVM does. This article does not implement MVVM, but instead shows how to build the model and view independent of each other.
Silverlight has been around for quite some time now and I hope most of you who have been working on Silverlight 3.0, might have started migrating to Silverlight 4.0. As you are aware, Silverlight is now used for developing LOB applications where the requirement is to develop loosely coupled browser based applications using Silverlight. One of the approaches here is to remove the dependency between Model  and View (UI) so that they can be developed and tested independent from each other. This article shows how to create a Silverlight application that consumes a WCF service keeping minimum dependencies between the Model and View
Note: This article does not use the MVVM approach as indicated earlier. Check out the MIX session by Laurent to know more about building MVVM applications    http://live.visitmix.com/MIX10/Sessions/EX14
In this article, I have used WCF service which is responsible for Database communication. You can use ADO.NET entity framework and ADO.NET Data service instead of writing data access code in WCF, but we will leave that to a different article.
Note: In this article I have used VS2010 RC, WCF 4.0 and Silverlight 4.0.
Step 1: Open VS2010 and create a blank solution, name it as ‘SILV4_MVVM’.
Step 2: To this solution, add a WCF application project, name it as ‘WCF_DataService’. Rename ‘IService1’ to ‘IService’ and ‘Service1.svc’ to ‘Service.svc’.
Step 3: To this WCF Service project, add a new class and name it as ‘DbManager’. This class will act as a Database communication class. Write the implementation of the class as shown below [Please use try catch blocks where required]
C#
using System.Data;
using System.Data.SqlClient;
 
namespace WCF_DataService
{
    public static class DbManager
    {
        static SqlConnection Conn;
 
        public static void OpenConnection()
        {
            Conn = new SqlConnection("Data Source=.\\dbServer;Initial Catalog=Company;Integrated Security=SSPI");
            Conn.Open();
        }
 
        public static DataTable GetAllRecords(string query)
        {
            SqlCommand Cmd = new SqlCommand();
            Cmd.Connection = Conn;
            Cmd.CommandText = query;
 
            SqlDataReader Reader = Cmd.ExecuteReader();
 
            DataTable dtVal = new DataTable();
            dtVal.Load(Reader);
 
            return dtVal;
        }
 
        public static void PerformDML(string query)
        {
            SqlCommand Cmd = new SqlCommand();
            Cmd.Connection = Conn;
            Cmd.CommandText = query;
 
            Cmd.ExecuteNonQuery();
        }
 
        public static void CloseConnection()
        {
            if (Conn.State == ConnectionState.Open)
            {
                Conn.Close();
            }
        }
    }
}
 
VB.NET
 
Imports System.Data
Imports System.Data.SqlClient
 
Namespace WCF_DataService
      Public NotInheritable Class DbManager
            Private Shared Conn As SqlConnection
 
            Private Sub New()
            End Sub
            Public Shared Sub OpenConnection()
                  Conn = New SqlConnection("Data Source=.\dbServer;Initial Catalog=Company;Integrated Security=SSPI")
                  Conn.Open()
            End Sub
 
            Public Shared Function GetAllRecords(ByVal query As String) As DataTable
                  Dim Cmd As New SqlCommand()
                  Cmd.Connection = Conn
                  Cmd.CommandText = query
 
                  Dim Reader As SqlDataReader = Cmd.ExecuteReader()
 
                  Dim dtVal As New DataTable()
                  dtVal.Load(Reader)
 
                  Return dtVal
            End Function
 
            Public Shared Sub PerformDML(ByVal query As String)
                  Dim Cmd As New SqlCommand()
                  Cmd.Connection = Conn
                  Cmd.CommandText = query
 
                  Cmd.ExecuteNonQuery()
            End Sub
 
            Public Shared Sub CloseConnection()
                  If Conn.State = ConnectionState.Open Then
                        Conn.Close()
                  End If
            End Sub
      End Class
End Namespace
 
Step 4: Write the following code in ‘IService.cs’
C#
 
namespace WCF_DataService
{
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        Employee[] GetAllEmployees();
    }
 
 
    [DataContract]
    public class Employee
    {
        [DataMember]
        public int EmpNo { get; set; }
        [DataMember]
        public string EmpName { get; set; }
        [DataMember]
        public int Salary { get; set; }
        [DataMember]
        public int DeptNo { get; set; }
    }
}
 
VB.NET
 
Namespace WCF_DataService
      <ServiceContract> _
      Public Interface IService
            <OperationContract> _
            Function GetAllEmployees() As Employee()
      End Interface
 
 
      <DataContract> _
      Public Class Employee
            Private privateEmpNo As Integer
            <DataMember> _
            Public Property EmpNo() As Integer
                  Get
                        Return privateEmpNo
                  End Get
                  Set(ByVal value As Integer)
                        privateEmpNo = value
                  End Set
            End Property
            Private privateEmpName As String
            <DataMember> _
            Public Property EmpName() As String
                  Get
                        Return privateEmpName
                  End Get
                  Set(ByVal value As String)
                        privateEmpName = value
                  End Set
            End Property
            Private privateSalary As Integer
            <DataMember> _
            Public Property Salary() As Integer
                  Get
                        Return privateSalary
                  End Get
                  Set(ByVal value As Integer)
                        privateSalary = value
                  End Set
            End Property
            Private privateDeptNo As Integer
            <DataMember> _
            Public Property DeptNo() As Integer
                  Get
                        Return privateDeptNo
                  End Get
                  Set(ByVal value As Integer)
                        privateDeptNo = value
                  End Set
            End Property
      End Class
End Namespace
 
The above code shows the ServiceContract as well as DataContract used in WCF service.
Step 5: Open Service.cs and write the following implementation:
C#
 
namespace WCF_DataService
{
    public class Service : IService
    {
 
        public Employee[] GetAllEmployees()
        {
            DbManager.OpenConnection();
 
            string strEmp = "Select * from Employee";
 
            DataTable dtVal = DbManager.GetAllRecords(strEmp);
 
            Employee[] arrEmp = new Employee[dtVal.Rows.Count];
 
            int i = 0;
            foreach (DataRow Dr in dtVal.Rows)
            {
                arrEmp[i] = new Employee()
                {
                    EmpNo = Convert.ToInt32(Dr["EmpNo"]),
                    EmpName = Dr["EmpName"].ToString(),
                    Salary = Convert.ToInt32(Dr["Salary"]),
                    DeptNo = Convert.ToInt32(Dr["DeptNo"])
                };
                i++;
            }
 
            DbManager.CloseConnection();
 
            return arrEmp;
        }
 
    }
}
 
VB.NET
 
Namespace WCF_DataService
      Public Class Service
            Implements IService
 
            Public Function GetAllEmployees() As Employee()
                  DbManager.OpenConnection()
 
                  Dim strEmp As String = "Select * from Employee"
 
                  Dim dtVal As DataTable = DbManager.GetAllRecords(strEmp)
 
                  Dim arrEmp(dtVal.Rows.Count - 1) As Employee
 
                  Dim i As Integer = 0
                  For Each Dr As DataRow In dtVal.Rows
                        arrEmp(i) = New Employee() With {.EmpNo = Convert.ToInt32(Dr("EmpNo")), .EmpName = Dr("EmpName").ToString(), .Salary = Convert.ToInt32(Dr("Salary")), .DeptNo = Convert.ToInt32(Dr("DeptNo"))}
                        i += 1
                  Next Dr
 
                  DbManager.CloseConnection()
 
                  Return arrEmp
            End Function
 
      End Class
End Namespace
 
Step 6: Build the service and publish it in IIS. To test this service, make sure that you are able to successfully browse Service.svc and can see the WSDL. 
Note: We are not making any changes in Web.Config file because WCF 4.0 has default configuration. This uses ‘basicHttpBinding’ and since this WCF service is going to be used in Silverlight, BasicHttpBinding is any way required.
Creating a Silverlight client
 
Step 7: To the solution, add a new ‘Silverlight Class Library’ project and name it as ‘Silv4.Company.View.ModelVew’. To this project, add two new folders - first named as ‘Model’ which contains all model classes. The second folder named ‘ViewModel’ which contains all ViewModel classes.
Step 8: To this project, add service reference to the WCF service. As soon as you do that, you will see that Service Reference and ‘ServiceReferences.config’ gets added to the project. The project structure will be as shown below:
SolutionExplorer
This service reference will add ‘Employee’ class.
Step 9: In the model folder, add a new class and name it as ‘EmployeeOperationEventArgs’. This class contains arguments definition, which will contain data from Model to View. The code is as shown below:
C#
 
using Silv4.Company.View.ModelVew.MyRef;
 
namespace Silv4.Company.View.ModelVew.Model
{
    public class EmployeeOperationsEventArgs : EventArgs
    {
        //Declare a Enumerable, representing return values, when call is made to the service
        public IEnumerable<Employee> AllEmployees { get; set; }
 
        public EmployeeOperationsEventArgs(IEnumerable<Employee> allEmployees)
        {
            AllEmployees = allEmployees;
        }
    }
}
 
VB.NET
 
Imports Silv4.Company.View.ModelVew.MyRef
 
Namespace Silv4.Company.View.ModelVew.Model
      Public Class EmployeeOperationsEventArgs
            Inherits EventArgs
            'Declare a Enumerable, representing return values, when call is made to the service
            Private privateAllEmployees As IEnumerable(Of Employee)
            Public Property AllEmployees() As IEnumerable(Of Employee)
                  Get
                        Return privateAllEmployees
                  End Get
                  Set(ByVal value As IEnumerable(Of Employee))
                        privateAllEmployees = value
                  End Set
            End Property
 
            Public Sub New(ByVal allEmployees As IEnumerable(Of Employee))
                  AllEmployees = allEmployees
            End Sub
      End Class
End Namespace
 
Step 10: In the Model folder, add a new interface and name it as ‘IEmployee’. Write the following code:
C#
 
namespace Silv4.Company.View.ModelVew.Model
{
    public interface IEmployee
    {
        void GetAllEmployees();
        //The Following event is used for notification
        //for the Operation completed by the ViewModel.
        //This is REquired because the SIlverlight applications
        //makes async call to service.
 
        event EventHandler<EmployeeOperationsEventArgs> GetAllEmployeesCompleted;
 
    }
}
 
VB.NET
 
Namespace Silv4.Company.View.ModelVew.Model
      Public Interface IEmployee
            Sub GetAllEmployees()
            'The Following event is used for notification
            'for the Operation completed by the ViewModel.
            'This is REquired because the SIlverlight applications
            'makes async call to service.
 
            Event GetAllEmployeesCompleted As EventHandler(Of EmployeeOperationsEventArgs)
 
      End Interface
End Namespace
 
The interface contains a method called ‘GetAllEmployees’ which is used to make a call to the WCF service using proxy. The event ‘GetAllEmployeeCompleted’ is used for notification, when the fetch of the data is completed. This event is required because Silverlight makes an asynchronous call to WCF services.
Step 11: To the Model folder, add a new class and name it as ‘EmployeeModel’. This class implements ‘IEmployee’. This class makes a call to the WCF service using proxy. The implementation is as shown below:
C#
 
using Silv4.Company.View.ModelVew.MyRef;
 
namespace Silv4.Company.View.ModelVew.Model
{
    //This class is responsible for making call to the Service and perform Data operations
    public class EmployeeModel : IEmployee
    {
        ServiceClient Proxy;
 
        Employee[] arrEmp;
 
        public EmployeeModel()
        {
            Proxy = new ServiceClient();
        }
        public void GetAllEmployees()
        {
            Proxy.GetAllEmployeesCompleted += new EventHandler<GetAllEmployeesCompletedEventArgs>(Proxy_GetAllEmployeesCompleted);
            Proxy.GetAllEmployeesAsync();
        }
 
        void Proxy_GetAllEmployeesCompleted(object sender, GetAllEmployeesCompletedEventArgs e)
        {
            if (e.Result != null)
            {
                arrEmp = e.Result;
                //Raise The event
                GetAllEmployeesCompleted(this, new EmployeeOperationsEventArgs(arrEmp));
            }
        }
 
        public void CreateEmployee()
        {
            throw new NotImplementedException();
        }
 
        public event EventHandler<EmployeeOperationsEventArgs> GetAllEmployeesCompleted;
 
        public event EventHandler NewEmployeeCreated;
    }
}
 
VB.NET
 
Imports Silv4.Company.View.ModelVew.MyRef
 
Namespace Silv4.Company.View.ModelVew.Model
      'This class is responsible for making call to the Service and perform ‘Data operations
      Public Class EmployeeModel
            Implements IEmployee
            Private Proxy As ServiceClient
 
            Private arrEmp() As Employee
 
            Public Sub New()
                  Proxy = New ServiceClient()
            End Sub
            Public Sub GetAllEmployees()
                  AddHandler Proxy.GetAllEmployeesCompleted, AddressOf Proxy_GetAllEmployeesCompleted
                  Proxy.GetAllEmployeesAsync()
            End Sub
 
            Private Sub Proxy_GetAllEmployeesCompleted(ByVal sender As Object, ByVal e As GetAllEmployeesCompletedEventArgs)
                  If e.Result IsNot Nothing Then
                        arrEmp = e.Result
                        'Raise The event
                        RaiseEvent GetAllEmployeesCompleted(Me, New EmployeeOperationsEventArgs(arrEmp))
                  End If
            End Sub
 
            Public Sub CreateEmployee()
                  Throw New NotImplementedException()
            End Sub
 
            Public Event GetAllEmployeesCompleted As EventHandler(Of EmployeeOperationsEventArgs)
 
            Public Event NewEmployeeCreated As EventHandler
      End Class
End Namespace
 
The ‘GetAllEmployee()’ method makes an asynchronous call to the WCF service. When the call is completed from the Model to the WCF service, the ‘GetEmployeeCompleted’ event is raised. The argument to this event is the result returned by WCF service (marked in bold italics).   
The above class represents implementation of the Model class. One thing I would like to tell you is to keep things simple, the above class does not include any failure or exception condition. So you can think of implementation of an error condition. Also I haven’t included the ‘CreateEmployee()’ method, you can do that also.
Step 12: In the ViewModel folder, add a class and name it as ‘’EmployeeViewModel . This class is used as a bridge between View and Model class. This class also defines Events which are used to receive notification from the Model and fire on the View so that data can be displayed. The implementation of the class is as shown below:
C#
using Silv4.Company.View.ModelVew.MyRef;
 
using Silv4.Company.View.ModelVew.Model;
using System.Collections.ObjectModel;
 
namespace Silv4.Company.View.ModelVew.ViewModel
{
 
    //The class Makes the use of the EmployeeModel class
    //by using the IEmployee interface it subscribe to the Model class
    //to perform operations.
    //This class makes use of events for the notification to UI.
    public class EmployeeViewModel
    {
        IEmployee empModel;
 
        //The important here is that, declare
       //collection type so that, it will
        //contain collection result so that
        //it will be made available to View
 
        ObservableCollection<Employee> allEmployees = new ObservableCollection<Employee>();
 
        public ObservableCollection<Employee> AllEmployees
        {
            get { return allEmployees; }
        }
 
 
        //Now you need to declare events.
        //These events will receive notification form
        //Model and fire on the view
 
        public event EventHandler GetAllEmployeeView;
        public event EventHandler NewEmployeeCreatedView;
 
        //This is used for Xaml binding in View
        public EmployeeViewModel()
            : this(new EmployeeModel())
        {
 
        }
        public EmployeeViewModel(IEmployee eModel)
        {
            empModel = eModel;
            empModel.GetAllEmployeesCompleted += new EventHandler<EmployeeOperationsEventArgs>(eModel_GetAllEmployeesCompleted);
        }
        //This will fire an event on UI thread (View)
        void eModel_GetAllEmployeesCompleted(object sender, EmployeeOperationsEventArgs e)
        {
            Application.Current.RootVisual.Dispatcher.BeginInvoke(() =>
            {
                allEmployees.Clear();
 
                foreach (Employee emp in e.AllEmployees)
                {
                    allEmployees.Add(emp);
                }
 
                //Raise event of completion
                if (GetAllEmployeeView != null)
                {
                    GetAllEmployeeView(this, null);
                }
 
            }
                );
        }
 
        //Make call to Method in the Model Class
 
        public void GetAllEmployees()
        {
            empModel.GetAllEmployees();
        }
 
    }
}
 
VB.NET
 
Imports Silv4.Company.View.ModelVew.MyRef
 
Imports Silv4.Company.View.ModelVew.Model
Imports System.Collections.ObjectModel
 
Namespace Silv4.Company.View.ModelVew.ViewModel
 
      'The class Makes the use of the EmployeeModel class
      'by using the IEmployee interface it subscribe to the Model class
      'to perform operations.
      'This class makes use of events for the notification to UI.
      Public Class EmployeeViewModel
            Private empModel As IEmployee
 
            'The important here is that, declare
            'collection type so that, it will
            'contain collection result so that
            'it will be made available to View
 
            Private allEmployees_Renamed As New ObservableCollection(Of Employee)()
 
            Public ReadOnly Property AllEmployees() As ObservableCollection(Of Employee)
                  Get
                        Return allEmployees_Renamed
                  End Get
            End Property
 
 
            'Now you need to declare events.
            'These events will receive notification form
            'Model and fire on the view
 
            Public Event GetAllEmployeeView As EventHandler
            Public Event NewEmployeeCreatedView As EventHandler
 
            'This is used for Xaml binding in View
            Public Sub New()
                  Me.New(New EmployeeModel())
 
            End Sub
            Public Sub New(ByVal eModel As IEmployee)
                  empModel = eModel
                  AddHandler empModel.GetAllEmployeesCompleted, AddressOf eModel_GetAllEmployeesCompleted
            End Sub
'This will fire an event on UI thread (View)
            Private Sub eModel_GetAllEmployeesCompleted(ByVal sender As Object, ByVal e As EmployeeOperationsEventArgs)
                        'Raise event of completion
                  Application.Current.RootVisual.Dispatcher.BeginInvoke(Function() AnonymousMethod1(e))
            End Sub
           
            Private Function AnonymousMethod1(ByVal e As EmployeeOperationsEventArgs) As Boolean
                  allEmployees_Renamed.Clear()
                  For Each emp As Employee In e.AllEmployees
                        allEmployees_Renamed.Add(emp)
                  Next emp
                  RaiseEvent GetAllEmployeeView(Me, Nothing)
                  Return True
            End Function
 
            'Make call to Method in the Model Class
 
            Public Sub GetAllEmployees()
                  empModel.GetAllEmployees()
            End Sub
 
      End Class
End Namespace
 
The event notification method i.e. eModel_GetAllEmloyeesCompleted, fires an event on the View and inserts all the fetched data from the Model into the Observable Collection. This raises the event GetAllEmployeeView which is used to notify to the View.
Build the project and make sure that it is error free.
Creating Silverlight View
 
In this step, we will create a Silverlight View.
Step 13: To the solution, add a new Silverlight application and name it as ‘SILV4_ClientApplication’. To this project, add a reference to ‘Silv4.Company.View.ModelVew’.
Step 14: In the Silverlight application, add a new folder and name it as ‘Views’. In this folder, add a new Silverlight UserControl and name it as ‘viewGetAllEmployees’. Using the Drag-Drop features of VS 2010 Silverlight designer, add a Button and a Datagrid to the designer.
Step 15: In viewGetAllEmployees.xaml.cs, write the following code:
C#
EmployeeViewModel empViewModel;
 
public viewGetAllEmployees()
{
    InitializeComponent();
    empViewModel = new EmployeeViewModel();
    empViewModel.GetAllEmployeeView += new EventHandler(empViewModel_GetAllEmployeeView);
}
 
void empViewModel_GetAllEmployeeView(object sender, EventArgs e)
{
 
    ObservableCollection<Employee> Employees = empViewModel.AllEmployees;
    dgEmp.ItemsSource = Employees;
 
    HtmlPage.Window.Alert("Data Fetched.."); 
}
 
private void btnLoadEmployee_Click(object sender, RoutedEventArgs e)
{
    empViewModel.GetAllEmployees();
}
 
VB.NET
Private empViewModel As EmployeeViewModel
 
Public Sub New()
      InitializeComponent()
      empViewModel = New EmployeeViewModel()
      AddHandler empViewModel.GetAllEmployeeView, AddressOf empViewModel_GetAllEmployeeView
End Sub
 
Private Sub empViewModel_GetAllEmployeeView(ByVal sender As Object, ByVal e As EventArgs)
 
      Dim Employees As ObservableCollection(Of Employee) = empViewModel.AllEmployees
      dgEmp.ItemsSource = Employees
 
      HtmlPage.Window.Alert("Data Fetched..")
End Sub
 
Private Sub btnLoadEmployee_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
      empViewModel.GetAllEmployees()
End Sub
 
The above code shows that on the View, event from the ViewModel class is raised. When the button is clicked, the View makes a call to the ViewModel class to the GetAllEmployee(). This method raises the event to which the View (UI) is subscribing. The data fetched from the ViewModel is notified to UI and bound with the DataGrid.
Step 16: Run the application and if everything’s ok, the following result will be displayed:
LoadAllEmployees
Conclusion: This article demonstrated how to build a Silverlight application that consumes a WCF service keeping minimum dependencies between the Model and View. This article does not use the MVVM approach. Check out the MIX session by Laurent to know more about building MVVM applications    http://live.visitmix.com/MIX10/Sessions/EX14
The entire source code of this article can be downloaded over here
Update: Comments have been disabled for this article to avoid further confusion.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce the The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this eBook aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and the C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Mahesh Sabnis is a DotNetCurry author and Microsoft MVP having over 17 years of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions). Follow him on twitter @maheshdotnet


Page copy protected against web site content infringement 	by Copyscape




Categories

JOIN OUR COMMUNITY

POPULAR ARTICLES

C# .NET BOOK

C# Book for Building Concepts and Interviews

Tags

JQUERY COOKBOOK

jQuery CookBook