Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Silverlight MVVM and Validation through WCF

0.00/5 (No votes)
5 Jun 2013 1  
Data validation example for Silverlight WCF enabled project
Sample Image - maximum width is 600 pixels

Introduction

This article explains how you can add and enable validation logic in simple POCO (Plain Old Clr Objects) and how they can be consumed by a Silverlight Client through a WCF data service.

Background

I wrote this article because while I was creating a simple validation test project in Silverlight .NET, the validation rules applied to my model didn't fire on the consumer side of the WCF-Service (in this case, a Silverlight Client). I was wondering why the rules didn't get fired when my WCF Data Service was consumed by the client and came to the conclusion that the referenced model class on the client created by the proxy didn't include the validation attributes which I added to the model class. This article shows you a possible solution for this issue.

Architecture

The sample application represents a typical MVVM (Model View ViewModel) architecture. I briefly explain the different projects embedded in the solution:

  • MVVM_Base: Base ViewModel project which exposes some classes for enabling the MVVM architecture and validation
  • MVVM_DataService: Exposes the WCF services which can be consumed by the client
  • MVVM_Model_SL: Silverlight Class Library which holds our model class
  • MVVM_MyValidation: Silverlight Client Application
  • MVVM_MyValidation.Web: Hosting WebSite
An in depth explanation of the MVVM pattern is beyond the scope of this article. So the reader should be familiar with the basic MVVM concepts.

The Model

I kept the model quit simple, just holding two properties with simple attribute validation. The validation triggering logic is encapsulated in the ValidatingViewModelBase class, which is part of the MVVM base project.

 public class Employee : ValidatingViewModelBase
 {
     private string _firstName;

     [Required(ErrorMessage="Firstname is required!")]
     public string FirstName
     {
         get { return _firstName; }
         set { _firstName = value; OnPropertyChanged("FirstName"); }
     }

     private string _lastName;

     [Required(ErrorMessage = "Lastname is required!")]
     public string LastName
     {
         get { return _lastName; }
         set { _lastName = value; OnPropertyChanged("LastName"); }
     }
 }
If you look at the code (supplied in the zipfile) for the MVVM_Model_SL project, you will notice that I've added links to the MVVM base classes. I had to do this because I implemented the MVVM_Base project as a ordinary class library (and not a specific Silverlight Class Library), so I can re-use my MVVM implementation in other projects.  Adding the links was necessary because you can't reference an ordinary Class Library within a Silverlight Class Library project.

The Data Service

  • The service is a WCF service which implements the IEmployeeService and exposes the method GetEmployees.
  • The implementation class returns a list of employee objects.
using MVVM_Model_SL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace MVVM_DataService
{
    [ServiceContract]
    public interface IEmployeeService
    {
        [OperationContract]
        List<employee /> GetEmployees();
    }

}
using MVVM_Model_SL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace MVVM_DataService
{
    public class EmployeeService : IEmployeeService
    {

        public List<employee /> GetEmployees()
        {
            return
            new List<employee />(){
                new Employee{FirstName="Marc",LastName="Spencer"},
                new Employee{FirstName="Julie",LastName="Matthews"};
        }
    }
}

The ViewModel

  • The ViewModel is part of our Silverlight application and is the glue between the View and our WCF Data Service.
  • The View communicates with and gets its data through the ViewModel.
  • The code from the ViewModel is quite self-explanatory.
namespace MVVM_MyValidation.ViewModels
{
    public class EmployeeViewModel : MVVM_Base.ValidatingViewModelBase
    {
        #region Storage

        // Instance of the Service Client
        private EmployeeServiceClient _serviceClient;

        // Holds the returned employees as an Observable Collection
        private ObservableCollection<employee /> _employeeList;
        public ObservableCollection<employee /> EmployeeList
        {
            get { return _employeeList; }
            set { _employeeList = value; OnPropertyChanged("EmployeeList"); }
        }

        #endregion Storage

        #region Ctor

        public EmployeeViewModel()
        {
            // Create the Service client a get the employees
            _serviceClient = new EmployeeServiceClient();
            RefreshEmployees();
        }

        #endregion Ctor

        #region Public Interface

        // Get the Number of Employees in the Collection
        public Int32 NumberOfEmployees
        {
            get { return _employeeList.Count; }
        }

        // Set/Get the Current Employee
        private Employee _currentEmployee;
        public Employee CurrentEmployee
        {
            get { return _currentEmployee; }
            set { _currentEmployee = value; OnPropertyChanged("CurrentEmployee"); }
        }

        #endregion Public Interface

        #region Private Interface

        // Get the Employee List from the Service &
        // point to the first employee. This is done in an Async Way.
        private void RefreshEmployees()
        {
            _serviceClient.GetEmployeesCompleted += (s, e) =>
                {
                    EmployeeList = e.Result;
                    CurrentEmployee = EmployeeList.Count > 0 ? EmployeeList[0] : null;
                };

            _serviceClient.GetEmployeesAsync();
        }

        #endregion Private Interface
    }
}

The View

  • The View is part of the Silverlight Application.
  • The View sets its DataContext to the ViewModel.
namespace MVVM_MyValidation.Views
{
    public partial class EmployeeView : Page
    {
        private EmployeeViewModel _viewModel;

        public EmployeeView()
        {
            InitializeComponent();
            _viewModel = new EmployeeViewModel();

            Loaded += (s, e) =>
                {
                    DataContext = _viewModel;
                };
        }

        // Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }
    }
}

Once the DataContext is set, the View can easily bind to its properties through the databinding capabilities in .NET. Next code snippets highlight and document the most important parts:

Click to enlarge image

  • The DataGrid binds to the EmployeeList exposed by our ViewModel.
  • The DataColumns bind to the exposed properties of the Employee.
  • The CurrentEmployee holds a reference to the current selected Employee in the DataGrid.
  • The TextBoxes bind to the properties of the CurrentEmployee.

The most interesting parts of our View's binding are the detail columns, which let the user modify the contents of the current Employee properties. The fact that validation exception is activated on the bound properties (through ValidatesOnDataErrors and ValidatesOnExceptions attributes). Strange enough unless you explicitly add the model as reference to the project and configure the service reference to reuse types in all referenced assemblies, validation will not be triggered. The cause is that the generated proxy code from the reference doesn't include the validation code on the client side. So you have to "bypass" this generated class in some way by adding the original model class as a reference to the client project and make sure that the service proxy reference is configured to reuse all types in all referenced assemblies. This way, the GUI will be bound to the model class instead of the  generated proxy class. As the original model class contains the validation attributes, data validation will occur. The configuration steps to achieve this are shown below:

*Step 1: Add the model as reference to the client project:

*Step 2: Configure the service reference to reuse types in all referenced assemblies:

That's all folks!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here