Friday, October 23, 2009

Fluent Validation


I was looking for a validation rules implementation methodology on my business entities without breaking the SRP. I was comfortable using the validation application block and had some techniques to integrate with my WPF applications. Recently I stopped on the codeplex site on a project that uses fluent interfaces and lambda expressions for building validation rules on business objects.  Jeremy Skinner has done a wonderful job by creating the Fluent Validation library. Using the library is easy and uses very little code for writing the validation rules.
I have created a sample application to demonstrate the usage of Fluent Validation.
public class Customer : BaseEntity<Guid>
{
    public string Name { get; set; }
    public string Email { get; set; }
    public IList<Order> Orders { get; set; }
    public Address Address { get; set; }
}
public class Order : BaseEntity<Guid>
{
    public string Name { get; set; }
    public DateTime Date { get; set; }
    public decimal Amount { get; set; }
    public int Quantity { get; set; }
}
The next step is to create your Validator classes for the entities.
public class OrderValidator : AbstractValidator<Order>
{
    public OrderValidator()
    {
        RuleFor<string>(x => x.Name).NotNull().NotEmpty().WithMessage("Name cannot be null or empty").WithPropertyName("Name");
        RuleFor<string>(x => x.Name).Length(1, 25)
            .WithMessage("Name should be in the range 0 - 25").WithPropertyName("Name");
        RuleFor<Guid>(x => x.Id).NotEqual(Guid.Empty).WithMessage("Id cannot be empty").WithPropertyName("Id");
        RuleFor<DateTime>(x => x.Date).LessThan(DateTime.Today)
            .WithMessage("Order date cannot be greater than today's date").WithPropertyName("Date");
        RuleFor<DateTime>(x => x.Date).Must((x, y) => x.Date > new DateTime(1900, 01, 01))
            .WithMessage("Order date should be greater than Jan, 01 1900").WithPropertyName("Date");
    }
}
public class CustomerValidator : AbstractValidator<Customer>
{
    public CustomerValidator()
    {
        RuleFor<string>(x => x.Name).NotEmpty().NotNull()
            .WithMessage("Name cannot be empty or null").WithPropertyName("Name");
        RuleFor<string>(x => x.Name).Length(1, 25)
            .WithMessage("Name should be of length 1 - 25").WithPropertyName("Name");
        RuleFor<IList<Order>>(x => x.Orders).SetValidator(new OrderValidator());
        RuleFor<Address>(x => x.Address).SetValidator(new AddressValidator());
        RuleFor(x => x.Email).EmailAddress().WithMessage("Not a valid email").WithPropertyName("Email");
        RuleFor(x => x.Address).NotNull().WithMessage("Customer cannot be created without address").WithPropertyName("Address");
    }
}
Once the validators are defined you can validate the code like
[TestMethod]
public void Customer_with_invalid_email_id_is_created()
{
    ___Customer.Email = "invalid email";
    var __Results = ___CustomerValidator.Validate(___Customer);

    Assert.IsTrue(__Results.Errors.Count > 0);
    Assert.IsFalse(__Results.IsValid);
    Assert.IsTrue(__Results.Errors.Any(x => x.PropertyName == "Email"));

}

[TestMethod]
public void Customer_with_invalid_order_name_is_created()
{
    ___Customer.Orders[0].Name = "Invalid order name with more than 25 characters";
    var __Results = ___CustomerValidator.Validate(___Customer);

    Assert.IsTrue(__Results.Errors.Count > 0);
    Assert.IsFalse(__Results.IsValid);
    Assert.IsTrue(__Results.Errors.Any(x => x.PropertyName == "Orders[0].Name"));
}
I’m using DI for getting the reference to my validator classes.
Container = new UnityContainer()
                .RegisterType<IValidator<Customer>, CustomerValidator>()
                .RegisterType<IValidator<Address>, AddressValidator>()
                .RegisterType<IValidator<Order>, OrderValidator>();
The validator instance is retrieved in the code from the container as
___CustomerValidator = Container.Resolve<IValidator<Customer>>();

Tuesday, October 20, 2009

Infragistics xamDataCarousel - Part 2


In part 1 of this article I introduced a simple example to demonstrate the xamDataCarousel control and the usage. In this post I’ll show how to get the details of the active record selected on the control items.
For getting the details from the current selected record, we can use the WPF data binding features as in the code sample given below.
<StackPanel Grid.Row="2" Grid.Column="1" DataContext="{Binding ElementName=sampleDataCarousel, Path=ActiveRecord}">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        Grid.RowDefinitions>
        <TextBlock Text="Name :" FontWeight="Bold" Margin="0 0 0 5" HorizontalAlignment="Right" />
        <TextBlock Text="Current Department :" FontWeight="Bold" Grid.Row="1" Margin="0 0 0 5" HorizontalAlignment="Right" />
        <TextBlock Text="Salary Earned :" FontWeight="Bold" Grid.Row="2" Margin="0 0 0 5" HorizontalAlignment="Right" />
        <TextBlock Text="Calculated Bonus :" FontWeight="Bold" Grid.Row="3" Margin="0 0 0 5" HorizontalAlignment="Right" />
        <TextBlock Text="Email Address :" FontWeight="Bold" Grid.Row="4" Margin="0 0 0 5" HorizontalAlignment="Right" />
        <TextBlock Text="{Binding Path=Cells[Name].Value}" HorizontalAlignment="Left" Margin="5 0 0 0" Grid.Column="1" Grid.Row="0" />
        <TextBlock Text="{Binding Path=Cells[Department].Value}" HorizontalAlignment="Left" Margin="5 0 0 0" Grid.Column="1" Grid.Row="1" />
        <TextBlock Text="{Binding Path=Cells[Salary].Value}" HorizontalAlignment="Left" Margin="5 0 0 0" Grid.Column="1" Grid.Row="2" />
        <TextBlock Text="{Binding Path=Cells[Bonus].Value}" HorizontalAlignment="Left" Margin="5 0 0 0" Grid.Column="1" Grid.Row="3" />
        <TextBlock Text="{Binding Path=Cells[Email].Value}" HorizontalAlignment="Left" Margin="5 0 0 0" Grid.Column="1" Grid.Row="4" />
    Grid>
StackPanel>

 

Monday, October 19, 2009

Infragistics xamDataCarousel - Part 1


The Infragistics xamDataCarousel control uses the Carousel View and arranges data items along a specified path.  Carousel View emphasizes the proximity, sequence, and movement of your data. Classic artistic principles such as perspective, and creating the sense of depth, are used in Carousel Views to create the appearance of a pseudo-3D environment on flat video displays.
I’ll show how to use the xamDataCarousel control from Infragistics to create and present data. Before starting you will require the NetAdvantage pack from Infragistics to be downloaded. You can download the trial version from the infragistics website.
I will be using the employee data from the class given below to create the sample application.
public class Employee : INotifyPropertyChanged
{
    public Employee()
    {
        ___Name = string.Empty;
        ___Department = string.Empty;
        ___Salary = 0;
        ___Email = string.Empty;
    }

    public Employee(string name, string dept, decimal salary, string email)
    {
        ___Name = name;
        ___Department = dept;
        ___Salary = salary;
        ___Email = email;
    }

    private decimal ___Salary;
    private string ___Name;
    private string ___Department;
    private string ___Email;

    public string Name
    {
        get { return ___Name; }
        set
        {
            ___Name = value;
            RaisePropertyChanged("Name");
        }
    }

    public string Department
    {
        get { return ___Department; }
        set
        {
            ___Department = value;
            RaisePropertyChanged("Department");
        }
    }

    public decimal Salary
    {
        get { return ___Salary; }
        set
        {
            if (___Salary != value)
            {
                ___Salary = value;
                RaisePropertyChanged("Salary");
                Bonus = ___Salary * 45 / 100;
            }
        }
    }

    public string Email
    {
        get { return ___Email; }
        set
        {
            ___Email = value;
            RaisePropertyChanged("Email");
        }
    }

    public decimal Bonus { get; set; }
    public string ImagePath { get; set; }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}
In my ViewModel I have the references to the Employee collection as
public class ViewModel
{
    public ObservableCollection<Employee> EmployeeCollection { get; set; }   

    public ViewModel()       
    {
        EmployeeCollection = EmployeeFactory.GetCollection();
    }
}
The XAML code contains the fieldlayouts and style representation for the xamDataCaurosel control
<Window.Resources>
    <Style TargetType="{x:Type igdp:DataRecordCellArea}">
        <Setter Property="BackgroundHover">
            <Setter.Value>
                <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                    <GradientStop Color="#FF2225FF" Offset="0"/>
                    <GradientStop Color="#FFB9D8FF" Offset="1"/>
                LinearGradientBrush>
            Setter.Value>
        Setter>
        <Setter Property="BorderHoverBrush" Value="#FF000000"/>
    Style>
    <Style x:Key="CellImageStyle" TargetType="{x:Type igdp:CellValuePresenter}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type igdp:CellValuePresenter}">
                    <Image HorizontalAlignment="Left" VerticalAlignment="Bottom" Source="{Binding DataItem.ImagePath}" Height="50" Width="50" />
                ControlTemplate>
            Setter.Value>
        Setter>
    Style>
Window.Resources>
<igdp:XamDataCarousel Name="sampleDataCarousel"
                      DataSource="{Binding EmployeeCollection}"
                      Grid.Column="1" Grid.Row="1">
    <igdp:XamDataCarousel.ViewSettings>
        <igWindows:CarouselViewSettings IsListContinuous="True" ItemsPerPage="5" 
                                        OpacityEffectStopDirection="UseItemPath" UseOpacity="True"
                                        UseScaling="True" ScalingEffectStopDirection="UseItemPath">
            <igWindows:CarouselViewSettings.OpacityEffectStops>
                <igWindows:OpacityEffectStopCollection>
                    <igWindows:OpacityEffectStop Offset="0" Value="0" />
                    <igWindows:OpacityEffectStop Offset=".5" Value="1" />
                    <igWindows:OpacityEffectStop Offset="1" Value="0" />
                igWindows:OpacityEffectStopCollection>
            igWindows:CarouselViewSettings.OpacityEffectStops>
            <igWindows:CarouselViewSettings.ScalingEffectStops>
                <igWindows:ScalingEffectStopCollection>
                    <igWindows:ScalingEffectStop Offset="0" Value=".8" />
                    <igWindows:ScalingEffectStop Offset=".5" Value="1" />
                    <igWindows:ScalingEffectStop Offset="1" Value=".8" />
                igWindows:ScalingEffectStopCollection>
            igWindows:CarouselViewSettings.ScalingEffectStops>
        igWindows:CarouselViewSettings>
    igdp:XamDataCarousel.ViewSettings>
    <igdp:XamDataCarousel.FieldLayoutSettings>
        
        <igdp:FieldLayoutSettings AutoArrangeMaxRows="3" AutoGenerateFields="False" />
    igdp:XamDataCarousel.FieldLayoutSettings>
    <igdp:XamDataCarousel.FieldLayouts>
        <igdp:FieldLayout>
            <igdp:FieldLayout.Fields>
                <igdp:Field Name="Name" Label="Name" />
                <igdp:Field Name="ImagePath">
                    <igdp:Field.Settings>
                        <igdp:FieldSettings CellValuePresenterStyle="{StaticResource CellImageStyle}" />
                    igdp:Field.Settings>
                igdp:Field>
                <igdp:Field Name="Department" Label="Department" />
                <igdp:Field Name="Salary" Label="Salary" />
                <igdp:Field Name="Bonus" Label="Bonous" />
                <igdp:Field Name="Email" Label="Email Address" />
            igdp:FieldLayout.Fields>
        igdp:FieldLayout>
    igdp:XamDataCarousel.FieldLayouts>
igdp:XamDataCarousel>
The datacontext is set in the code behind file as
 this.DataContext = new ViewModel();
In the next part of the series I’ll show a sample how to display the details of the active record from the list.