Validation Using RIAServices in Silverlight


Introduction

We have seen how to validate in Silverlight using IdataErrorInfo. Here in this article we will see how to validate any input field using RIA Services. When I say RIA services, we will be using domain services and data annotation attributes to validate the input field.

Setting Up Silverlight Project

Open Visual Studio and create a new Silverlight application; in my case it is ValidationUsingRIAServices. So we will be provided two project one ValidationUsingRIAServices which is our Silverlight application and the other ValidationUsingRIAServices.Web which is our server application. One most important point is to check Enable RIA service while creation of this project.

Lets follow a step wise procedure to implement validation using RIA Services

1. Lets put some input field to our MainPage.xaml so that it will look something like:

SilRiaSrvc1.gif

2. Now its time for some database stuff. Lets choose any database and create a table tblEmployee and it will have the following design.

SilRiaSrvc2.gif

3. For the very next step will be adding a ADO.NET Entity data Model to our ValidationUsingRIAServices.Web once we will add the template the wizard will guide us through to choose the database and corresponding table and finally we will land up to with following scenario:

SilRiaSrvc3.gif

Just build the project so that when we add the domain service we will have tblEmployee available to include.

4. Now add a new item called domain service class; in my case I have named it as EmployeeService.cs. Once you add you will encounter following screen

SilRiaSrvc4.gif

From the screen we can see the entity tblEmployee is available to us to choose; lets choose checkbox for tblEmployee and we can see there is another checkbox "Enable editing" that is optional. Domain service automatically generate functions for CRUD(INSERT,READ,UPDATE,DELETE) operation for the entity which we have selected but out of 4 CRUD operation by default we get function for extracting data from the same entity, other three gets generated when we select enable edition option. Finally we need to make sure that we check the Generate associated classes for metadata. Once we are done we will get EmployeeService.cs class with following code automatically generated.

 [EnableClientAccess()]
    public class EmployeeService : LinqToEntitiesDomainService<DatabaseEntities>
    {      
        //READ
        public IQueryable<tblEmployee> GetTblEmployees()
        {
            return this.ObjectContext.tblEmployees;
        }

        //CREATE
        public void InsertTblEmployee(tblEmployee tblEmployee)
        {
            if ((tblEmployee.EntityState != EntityState.Detached))
            {
                this.ObjectContext.ObjectStateManager.ChangeObjectState(tblEmployee, EntityState.Added);
            }
            else
            {
                this.ObjectContext.tblEmployees.AddObject(tblEmployee);
            }
        }

        //UPDATE
        public void UpdateTblEmployee(tblEmployee currenttblEmployee)
        {
            this.ObjectContext.tblEmployees.AttachAsModified(currenttblEmployee, this.ChangeSet.GetOriginal(currenttblEmployee));
        }

        //DELETE
        public void DeleteTblEmployee(tblEmployee tblEmployee)
        {
            if ((tblEmployee.EntityState != EntityState.Detached))
            {
                this.ObjectContext.ObjectStateManager.ChangeObjectState(tblEmployee, EntityState.Deleted);
            }
            else
            {
                this.ObjectContext.tblEmployees.Attach(tblEmployee);
                this.ObjectContext.tblEmployees.DeleteObject(tblEmployee);
            }
        }
    }


With this the domain service creation has created another class EmployeeService.metadata.cs which looks like:

SilRiaSrvc5.gif

And inside that we can find codes which will look like:

 public partial class tblEmployee
    {
        internal sealed class tblEmployeeMetadata
        {

            // Metadata classes are not meant to be instantiated.
            private tblEmployeeMetadata()
            {
            }

            public string EmployeeAddress { get; set; }

            public string EmployeeDepartment { get; set; }

            public int EmployeeID { get; set; }

            public string EmployeeName { get; set; }
        }
    }

Lets put some dataannotation attributes to these field and lets make all the field required. After we put required attributes the code will look like

   public partial class tblEmployee
    {      
        internal sealed class tblEmployeeMetadata
        {

            // Metadata classes are not meant to be instantiated.
            private tblEmployeeMetadata()
            {
            }

            [Required]
            public string EmployeeAddress { get; set; }

            [Required]
            public string EmployeeDepartment { get; set; }

            [Required]
            public int EmployeeID { get; set; }

            [Required]
            public string EmployeeName { get; set; }
        }
    }

5. So we have completed all the server related work. Now we will move to Silverlight Application. Lets create a class with the same name tblEmployee. Lets make the class as partial class of tblEmployee. Here we are trying to create a partial class of the same entity that is tblEmployee which we have already defined in domain class.

          public partial class tblEmployee
          {

          }       

Finally to make it work we need to match the namespace of the metadata class
"EmployeeService.metadata.cs" with that of the class created in Silverlight application project. Sp we will change the namespace of partial class created in Silverlight application in match with that of metadata class in Silverlight web application.

6. We need to add code for validation and after adding the class will look like :-

namespace ValidationUsingRIAServices.Web
{
    public partial class tblEmployee
    {
        public bool ValidateEmployee(ValidationContext validationContext)
        {
            //Clear Previous valiadtion.
            ValidationErrors.Clear();  

            IDictionary<object, object> dictionaryItems = null;
            ValidationContext employeeValidationContext = new ValidationContext(this, validationContext, dictionaryItems);
            ICollection<ValidationResult> employeeValidationResults = new List<ValidationResult>();

            //Use tryValidateobject to validate
            if (Validator.TryValidateObject(this, employeeValidationContext, employeeValidationResults, true) == false)
            {
                //Adding Validation result to validation error
                foreach (ValidationResult validationError in employeeValidationResults)
                {
                    ValidationErrors.Add(validationError);
                }
                return false;
            }

            return true;
        }
    }
}

7. And Finally in MainPage.xaml.cs we need to create a property of tblClassEmployee for binding it to the xaml. Here we need to refer the domain services which we have created.And we need to bind the data so we will have code something like

 public partial class MainPage : UserControl
    {
        EmployeeContext dataContext = new EmployeeContext();

        private tblEmployee _newEmployee;
        public tblEmployee NewEmployee
        {
            get
            {
                return _newEmployee;
            }
            set
            {
                _newEmployee = value;
            }
        }
        public MainPage()
        {
            InitializeComponent();
            _newEmployee = new tblEmployee();

            employeeStackPanel.DataContext = NewEmployee;
        }

        private void AddEmployeeButton_Click(object sender, RoutedEventArgs e)
        {
            if (NewEmployee.ValidateEmployee(dataContext.ValidationContext) == false)
            {
                return;
            }

            //Go Ahead and do something
        }
    }

8. At the end of the code to the button click event of the code I have called ValidateEmployee which will validate the employee. And our XAML will look like

<StackPanel x:Name="employeeStackPanel">
            <StackPanel Orientation="Horizontal" Margin="0,10,0,0" >
                <sdk:Label x:Name="employeeIDLabel" Content="Employee ID:" Width="120" Margin="5,0,0,0" />
                <TextBox Width="200" Height="23" Margin="5,0,0,0" Text="{Binding EmployeeID, Mode=TwoWay}" />
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                <sdk:Label x:Name="employeeAddressLabel" Content="Employee Address:" Width="120" Margin="5,0,0,0" />
                <TextBox Width="200" Height="23" Margin="5,0,0,0" Text="{Binding EmployeeAddress, Mode=TwoWay}"  />
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                <sdk:Label x:Name="employeeNameLable" Content="Employee Name:" Width="120" Margin="5,0,0,0" />
                <TextBox Width="200" Height="23" Margin="5,0,0,0" Text="{Binding EmployeeName, Mode=TwoWay}" />
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                <sdk:Label x:Name="employeeDepartmentLable" Content="Employee Dept:" Width="120" Margin="5,0,0,0" />
                <TextBox Width="200" Height="23" Margin="5,0,0,0" Text="{Binding EmployeeDepartment, Mode=TwoWay}" />
            </StackPanel>
            <StackPanel Margin="100,10,0,0" HorizontalAlignment="Left"  >
                <Button x:Name="AddEmployeeButton" Width="100" Height="30" Content="Add Employee" Click="AddEmployeeButton_Click" />               
           
</StackPanel>
        </StackPanel>


9. And you are done When you will go and run the project the first screen which you will encounter is

.SilRiaSrvc6.gif

Once you will click on AddEmployeeButton you will face following screen .

SilRiaSrvc7.gif

SilRiaSrvc8.gif

Since in the Metadata class we have just used Required Attributes that is why we are getting required validation only we can change that with our requirement. We can have other attributes depending upon our requirement for example we can place regular expression attributes to match, again we can restrict string length of our input using StringLength attribute . I have changed few of them so my metadata class looks like

     internal sealed class tblEmployeeMetadata
        {

            // Metadata classes are not meant to be instantiated.
            private tblEmployeeMetadata()
            {
            }

            [Required(ErrorMessage="Employee Address is Required")] 
            [StringLength(200,MinimumLength = 10,ErrorMessage = "Employee Address can't be less than 10 characters")]
            public string EmployeeAddress { get; set; }

            [Required(ErrorMessage="Employee Department should be given")]
            [RegularExpression(@"^\d+$", ErrorMessage = "Numbers are allowed only")]
            public string EmployeeDepartment { get; set; }

            [Required]           
            public int EmployeeID { get; set; }

            [Required(ErrorMessage="Employee name should be given")]
            [RegularExpression(@"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$",ErrorMessage="Given Employee Name is Not Valid")]
            public string EmployeeName { get; set; }
        }


Here we have restricted EmployeeDepartment to have numeric data only and EmployeeName to have mail format and restricted length of employee address . So now the screen will look like.


Here we have set a policy for Employee Address

SilRiaSrvc9.gif

Here we are matching the Employee Name with the mail format.

SilRiaSrvc10.gif

Employee Department can just accept numbers only.

Hope this will Help !!!!!.
 


Similar Articles