# Monday, August 09, 2010

Note: This expands on the code created in my previous post: Implementing Attribute Based Domain Validation In a WPF MVVM Application

* Download Complete Source Code

Continuing on my WPF MVVM Adventures... My next task was to implement security on my composite application.  Unfortunately, as is all to often the case, there where still business decisions to be made concerning the granularity of the security {is field level required} and also the source of record {LDAP, roll-our-own}.  Not wanting to loose focus on the security piece and knowing I couldn’t sit around and do nothing I decided to tackle the one piece I knew that was constant…I was going to need a UI for logging in a user.

I started this process by creating a simple/standard log on window.

image  image 

LogOn.xaml
  1. <Window x:Class="CompositeAppPoc.Shell.LogOn"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.         Title="Log On" SizeToContent="WidthAndHeight"
  5.         WindowStartupLocation="CenterScreen" WindowStyle="None"
  6.         ResizeMode="NoResize" MinWidth="300" BorderThickness="4" AllowsTransparency="True">
  7.  
  8.     <Window.Resources>
  9.         <Style TargetType="TextBox">
  10.             <Setter Property="Margin" Value="4"/>
  11.             <Setter Property="MinWidth" Value="100"/>
  12.         </Style>
  13.         <Style TargetType="PasswordBox">
  14.             <Setter Property="Margin" Value="4"/>
  15.             <Setter Property="MinWidth" Value="100"/>
  16.         </Style>
  17.         <Style TargetType="Button">
  18.             <Setter Property="Margin" Value="4"/>
  19.             <Setter Property="MinWidth" Value="75"/>
  20.         </Style>
  21.     </Window.Resources>
  22.  
  23.     <Grid>
  24.         <Grid.ColumnDefinitions>
  25.             <ColumnDefinition Width="Auto"/>
  26.             <ColumnDefinition/>
  27.         </Grid.ColumnDefinitions>
  28.         <Grid.RowDefinitions>
  29.             <RowDefinition Height="Auto"/>
  30.             <RowDefinition Height="Auto"/>
  31.             <RowDefinition Height="Auto"/>
  32.             <RowDefinition Height="Auto"/>
  33.             <RowDefinition/>
  34.         </Grid.RowDefinitions>
  35.         <!-- Header -->
  36.         <StackPanel Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2">
  37.             <Label HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
  38.                    FontWeight="Bold" FontSize="16" Content="Log On">
  39.             </Label>
  40.         </StackPanel>
  41.         <!-- Main Controls -->
  42.         <Label Grid.Column="0" Grid.Row="1" HorizontalAlignment="Right" Content="User Name"/>
  43.         <TextBox Grid.Column="1" Grid.Row="1" GotFocus="CredentialsFocussed" x:Name="txtUsername"/>
  44.         <Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" Content="Password"/>
  45.         <PasswordBox Grid.Column="1" Grid.Row="2" GotFocus="CredentialsFocussed" x:Name="txtPassword" />
  46.         <Label Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" Foreground="Red" FontStyle="Italic" Visibility="{Binding ShowInvalidCredentials}" Content="*Invalid User Name and/or Password"/>
  47.         <StackPanel Grid.Column="0" Grid.Row="4" Grid.ColumnSpan="2" Orientation="Horizontal" VerticalAlignment="Bottom" Margin="5" HorizontalAlignment="Right" Height="Auto">
  48.             <Button Content="Log-on" Click="LogonClick" IsDefault="True"/>
  49.             <Button Content="Cancel" IsCancel="True"/>
  50.         </StackPanel>
  51.  
  52.     </Grid>
  53.  
  54. </Window>

LogOn.xaml.cs
  1. using System.ComponentModel;
  2. using System.Windows;
  3. using System.Windows.Controls;
  4. using System.Windows.Controls.Primitives;
  5.  
  6. namespace CompositeAppPoc.Shell {
  7.  
  8.     public partial class LogOn : Window, INotifyPropertyChanged {
  9.  
  10.         #region Private Fields
  11.  
  12.         private int _attempts;
  13.  
  14.         #endregion
  15.  
  16.         #region Public Properties
  17.  
  18.         public int Attempts {
  19.             get { return _attempts; }
  20.             set {
  21.                 if (value != _attempts) {
  22.                     _attempts = value;
  23.                     OnPropertyChanged("Attempts");
  24.                 }
  25.             }
  26.         }
  27.  
  28.         public Visibility ShowInvalidCredentials {
  29.             get {
  30.                 if (_attempts > 0) {
  31.                     return Visibility.Visible;
  32.                 }
  33.                 return Visibility.Hidden;
  34.             }
  35.         }
  36.  
  37.         public string UserName {
  38.             get { return txtUsername.Text; }
  39.         }
  40.  
  41.         public string Password {
  42.             get { return txtPassword.Password; }
  43.         }
  44.  
  45.         #endregion
  46.  
  47.         public LogOn() : this(string.Empty,string.Empty) {}
  48.  
  49.         public LogOn(string userName, string password) {
  50.             InitializeComponent();
  51.             DataContext = this;
  52.             txtUsername.Focus();
  53.             txtUsername.Text = userName;
  54.             txtPassword.Password = password;
  55.         }
  56.  
  57.         #region INotifyPropertyChanged Members
  58.  
  59.         public event PropertyChangedEventHandler PropertyChanged {
  60.             add { PropertyChangedEvent += value; }
  61.             remove { PropertyChangedEvent -= value; }
  62.         }
  63.  
  64.         #endregion
  65.  
  66.         private void LogonClick(object sender, RoutedEventArgs e) {
  67.             DialogResult = true;
  68.             Close();
  69.         }
  70.  
  71.         private void CredentialsFocussed(object sender, RoutedEventArgs e) {
  72.             TextBoxBase tb = sender as TextBoxBase;
  73.             if (tb == null) {
  74.                 PasswordBox pwb = sender as PasswordBox;
  75.                 pwb.SelectAll();
  76.             }
  77.             else {
  78.                 tb.SelectAll();
  79.             }
  80.         }
  81.  
  82.         private event PropertyChangedEventHandler PropertyChangedEvent;
  83.  
  84.         protected void OnPropertyChanged(string prop) {
  85.             if (PropertyChangedEvent != null)
  86.                 PropertyChangedEvent(this, new PropertyChangedEventArgs(prop));
  87.         }
  88.     }
  89. }

Now I have my Log On window but it doesn’t do anything.  I need to tell my application to show that window first.  Your first thought would be to go into the project properties and set LogOn as the startup object, but once you got in there you would notice that there is currently no startup object defined and this is by design.  Currently, because we are working with a composite application, all of that is handles by our Bootstrapper which is kicked off from App.xaml in the OnStartUp event.

App.xaml.cs (Old)
  1. using System.Windows;
  2.  
  3. namespace CompositeAppPoc.Shell {
  4.  
  5.     public partial class App : Application {
  6.  
  7.         protected override void OnStartup(StartupEventArgs e) {
  8.             base.OnStartup(e);
  9.             new Bootstrapper().Run();
  10.         }
  11.  
  12.     }
  13. }

We need to modify App.xaml.cs to:

  1. Show LogOn dialog
  2. Process result from LogOn dialog
    1. If ‘Cancel’ is clicked then close the application
    2. If ‘OK’ is clicked
      1. Perform authorization
        1. If authorized
          1. Run the bootstrapper
        2. If not authorized
          1. If exceeded the number of allowed attempts close the application
          2. Else…add 1 to the attempts, store username and password, and re-show the LogOn
App.xaml.cs (New)
  1. using System.Collections.Generic;
  2. using System.Windows;
  3. using CompositeAppPoc.Infrastructure.Entities;
  4. using CompositeAppPoc.Infrastructure.Services;
  5.  
  6. namespace CompositeAppPoc.Shell {
  7.  
  8.     public partial class App : Application {
  9.  
  10.         #region Private Fields
  11.  
  12.         private readonly AuthenticationService _authenticationService = new AuthenticationService();
  13.         private int _attempts;
  14.         private string _userName = "";
  15.         private string _pass = "";
  16.  
  17.         #endregion
  18.  
  19.         #region Private Methods
  20.         
  21.         private void ShowLogOn() {
  22.             var logon = new LogOn(_userName,_pass);
  23.             logon.Attempts = _attempts;
  24.             bool? res = logon.ShowDialog();
  25.             if (!res ?? true) {
  26.                 Shutdown(1);
  27.             }
  28.             else {
  29.                 AuthenticationContext ac = _authenticationService.Authenticate(logon.UserName, logon.Password);
  30.                 if (ac.IsAuthorized) {
  31.                     StartUp(ac.AllowedModules);
  32.                 }
  33.                 else {
  34.                     if (logon.Attempts > 2) {
  35.                         MessageBox.Show("Application is exiting due to invalid credentials", "Application Exit", MessageBoxButton.OK, MessageBoxImage.Error);
  36.                         Shutdown(1);
  37.                     }
  38.                     else {
  39.                         _attempts += 1;
  40.                         _userName = logon.UserName;
  41.                         _pass = logon.Password;
  42.                         ShowLogOn();
  43.                     }
  44.                 }
  45.             }
  46.         }
  47.  
  48.         private static void StartUp(IList<string> allowedModules) {
  49.             Current.MainWindow = null;
  50.             Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
  51.             var bs = new Bootstrapper();
  52.             bs.Run();
  53.             bs.LoadSecuredModules(allowedModules);
  54.         }
  55.  
  56.         #endregion
  57.  
  58.         #region Public Methods
  59.  
  60.  
  61.         public App() {
  62.             Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
  63.             ShowLogOn();
  64.         }
  65.  
  66.         #endregion
  67.     }
  68. }

That’s it, now we are requiring logging in to our application.  You may notice that there are bits in there that we haven’t covered yet, AuthenticationContext etc., this was me planning for the actual authentication implementation and can be replaced with whatever code you need.

Stay tuned for the actual security implementation.

* Download Complete Source Code

posted on Monday, August 09, 2010 4:02:00 PM (Central Daylight Time, UTC-05:00)  #    Comments [2]
# Thursday, July 29, 2010

Note: This expands on the code created in my previous post: WPF MVVM Multi-Solution Composite App

image

* Download Complete Source Code

Continuing on my WPF MVVM Adventures... My next task was to architect and code a validation framework that would:

  1. Adhere to the DRY principle.
  2. Allow me to define all validation in my domain objects.
  3. Allow me to easily relay validation issues to the UI/users.
  4. Allow me to easily add/modify validation rules.
  5. Not be *too* complex :)

Not wanting to re-invent the wheel I did some Googling, on Bing of course.  The first post that caught my eye was by Karl Shifflett, whom to me is one of the Grandfathers of WPF, and despite being a VB guy, usually has the answer.  So I read Karl’s article, downloaded the code and did some investigating.  The code would get the job done, but it wasn’t DRY.  Basically every field that was required had a check for not null and not empty, all validation code was done in the IDataErrorInfo’s Item override,  and even Karl himself recommends not doing it this way, and that you should use Ocean or another validation framework.  Not to discredit Karl, and I certainly recommend reading not only this post but all of Karl’s posts, but this didn’t fill all of my requirements.  Also, I am the type of developer who won’t use a framework for something I can code myself with out too much effort.

The next post that looked promising was by Josh Smith, whose Advanced MVVM book is a must read for anyone using MVVM.  Josh’s approach is nearly identical to Karl’s in that the base of the validation logic is repeated for every field.  Josh’s example also allows for further validation to be done at the ViewModel level, and this confuses me a little, in that the domain object itself should be the *gatekeeper* of valid object state.

So, having read these two posts from two of the more prominent WPF developers, and not finding what I wanted worried me.  Maybe I am totally missing something or what I want is flawed.  But hey, that’s why I blog…if I’m wrong call me out…and tell me why.

I started throwing some designs and thoughts down on paper and kept coming back to using attributes on the properties of domain objects.  Now, I am by no means a developer that pushes or even prefers attribute based solutions, but in this case it seemed to fit.

I knew that I was going to need an Interface or Abstract Base Class that would allow me to generically process the validators and always know what I was dealing with.  In this case I decided to go with an abstract base class just so I could have it inherit from Attribute and only require my instances of Validator to inherit a single class.  As you can see below the base class is very simple, it inherits Attribute and declares an abstract Validate method.  The other thing you’ll notice is that I decided to decorate the base class with the Attribute configuration.  This may change in the future, i.e. in some instances I may want to allow multiple of the same validator…say, if each is configurable.

  1: [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, 
  2:      AllowMultiple = false, Inherited = true)]
  3:  public abstract class ValidatorBase : Attribute {
  4:      public abstract string Validate(object value);
  5:  }

Now I need a validator.  Let’s start simple with a standard required field validator.  I created my class, made it inherit from ValidatorBase and coded the Validate override.

  1: public class ValidRequiredField : ValidatorBase {
  2: 
  3:     private const string _INVALID_REQUIRED_FIELD = "Required Field";
  4: 
  5:     public override string Validate(object value) {
  6:         try {
  7:              if (value == null || string.IsNullOrEmpty(value.ToString()))
  8:                  return _INVALID_REQUIRED_FIELD;
  9:         }
 10:         catch (NullReferenceException) {
 11:             return _INVALID_REQUIRED_FIELD;
 12:         }
 13:         return null; 
 14:     }
 15: }

The next step is decorate the properties in the domain entity with any validation attributes.  In this case I am decorating the LastName property with the ValidRequiredField attribute.

  1: [ValidRequiredField]
  2: public string LastName {
  3:     get { return _lastName; }
  4:     set {
  5:         if (_lastName != value) {
  6:             _lastName = value;
  7:             OnPropertyChanged("LastName");
  8:         }
  9:     }
 10: }

OK.  Cool.  Unfortunately, this by itself does nothing.  We have to kick off the validation and put in the processes that allow the ViewModel and UI to receive notification of validation issues.  We will start this process by creating an abstract base class that our domain entities will inherit from.  This abstract base class will implement INotifyPropertyChanged, and IDataErrorInfo.  I am sure we are all familiar with INotifyPropertyChanged so I am not going to go into detail on what needs to be done to implement that interface. 

IDataErrorInfo is what is going to allow us to fire off our validation and communicate any issues to the ViewModel and UI.  First we are going to create a Validate function that will accept a string parameter that represents the property name.  The function will verity that the passed in property name is valid and that a property with said name exists on the domain entity.  If the property exists, its value is retrieved.  The property is then interrogated for attributes of type ValidatorBase.  If/When one is found the validation logic is performed on that property.  A the validation of the property returns something other than null that means the property is invalid and a string containing details of the validation issue is returned.  If no validation issue is found on the current attribute then the next attribute is checked and the process continues until we are out of attributes or a validation issue is found.

  1: public string Validate(string propertyName) {
  2:     string result = null;
  3:     PropertyInfo prop = GetType().GetProperty(propertyName);
  4:     if (prop != null && !prop.Name.Equals("item", StringComparison.InvariantCultureIgnoreCase)) {
  5:         object value = prop.GetValue(this, null);
  6:         var attributes = (ValidatorBase[])prop.GetCustomAttributes(typeof(ValidatorBase), false);
  7:         foreach (ValidatorBase attribute in attributes) {
  8:             result = attribute.Validate(value);
  9:             if (result != null)
 10:                 return result;
 11:             }
 12:             return result;
 13:         }
 14:         return result;
 15:     }
 16: }

Next we will implement the contract for IDataErrorInfo.  This contract requires us to implement two properties, even know WPF only uses one of them.  The Item property is an enumerator for the collection of strings representing errors.  In the getter of this property we will return the results of calling our Validate function with the supplied property name.  This will later be hooked up in a round about way to the View via the ViewModel.

  1: public string this[string propertyName] {
  2:     get { return Validate(propertyName); }
  3: }
  4: 
  5: //Note: WPF does not use this function.
  6: public string Error {
  7:     get { return null; }
  8: }

This completes the plumbing for our validation framework.  There are an abundant number of blogs post on how to consume the IDataErrorInfo details in your views.  Beth Massi has done an excellent one which you can find here.

So, in wrapping up I feel like I have completed a validation framework that satisfies my goals.  Hopefully you will find it adaptable to your situation.

* Download Complete Source Code

posted on Thursday, July 29, 2010 11:00:00 PM (Central Daylight Time, UTC-05:00)  #    Comments [17]
# Monday, July 26, 2010

My current client is looking to combine a series of line of business Access (YIKES) and Win Forms apps into a composite WPF MVVM solution.  I was also brought in to architect one of the heavy hitter apps that will be a part of the new composite application.  In the initial discussion concerning creating a composite application, one of the client’s developers presented a proof of concept composite application using Microsoft’s Prism. I voiced my concern about the amount of code said solution would be required to handle and recommended going with a multi-solution composite rather than a multi-project composite.

I started researching multi-solution composite applications on the inter-webs and found very little, virtually no, useful material…and this worried me.  I couldn’t be the first guy to think the multi-solution approach would be preferred for a composite application that will, when all is said and done, contain hundreds of thousands of lines of code.  Not wanting to lead my client in the direction of the proverbial unicorn I decided to put together a little proof of concept of my own.

*Disclaimer*
This code is a Proof Of Concept and was developed as such.  The overall functionality of the application is trivial.  It is UI centric and does not contain a true data access layer and it does not contain any unit tests.  I know this is horrible but please understand. :)

The typical WPF composite application is broken down into three major sections.

  1. Infrastructure (VS Project)
    • Commands
    • Events
    • Domain Entities
    • Interfaces
  2. Shell (VS Project)
    • WPF Window that will act as the *shell* of your composite application
    • Bootstrapper (we will discuss this later)
  3. Modules (1 or more VS Projects)
    • WPF user controls that make up the functionality of your application
    • Modules should be as self contained as possible with minimal references to Infrastructure
    • Each module will contain
      • View
      • View Model
      • Controller (optional)

The structure for a multi-solution composite application is similar but is broken out into solutions instead of projects, surprise!

Solutions

The code is really straightforward.  There a couple of requirements though:

  1. Prism
  2. Unity

I included some UI enhancements, including implementing the Avalon Dock controls for docking windows.

Download Here!!!!!!

posted on Monday, July 26, 2010 10:49:00 PM (Central Daylight Time, UTC-05:00)  #    Comments [6]
# Saturday, July 24, 2010

On the way home from a weekend in Chicago for Midwest Give Camp a fellow developer and I got on the subject of what I like to call the “9 – 5 Developer.”  If Wikipedia had an entry for “9 –5 Developer” it would read:

  • A 9 – 5 Developer is a developer, typically found in the corporate arena, that is content with doing his daily development responsibilities using the least amount of effort possible.  While away from work they do nothing to better themselves in the development arena.  They are often found using technologies and techniques 2 –5 years behind what is current, and are content in doing so.  They are usually opposed to new things in fear that they would be required to learn.  Phrases often spoken by them include;
    • “If they think I am staying a minute after 5…they are crazy!”
    • “Why would I need to learn that when what I am doing works?”
    • “I would attend [insert free developer event] if the company paid me for my time.”
    • “[Boss] has something against me!  I am always being passed up for promotions.”

Don’t worry…if you are reading this…you are not a “9 – 5 Developer"! 

Being that I am a consultant I have ran in to more than my share.  If I had to estimate I would say, from my experience, 85% of all developers fall in this group.  I find that very disturbing.  I just can’t imagine being content going through life this way.

That’s my rant!  Thanks for stopping by!

posted on Saturday, July 24, 2010 10:01:00 PM (Central Daylight Time, UTC-05:00)  #    Comments [5]
# Wednesday, May 26, 2010

I am currently reading Agile Web Development with Rails by Sam Ruby, Dave Thomas, and David Heinemeier Hansson and I came across something very helpful early on in the book. As with most documentation these the complete Rails api documentation is available online which you can only access when you have an internet connection. As this is becoming less and less of a problem it is still a problem. So here are the steps for pulling down the documentation and always having it available when offline!

  1. > Open up Ruby command prompt
  2. > rails apidocs_app
  3. > cd apidocs_app
  4. > rake rails:freeze:gems
  5. > rake doc:rails
That's it. Now you can open up the index.html file created under apidocs/doc/api and have complete access to Rails api documentation whenever you need it!

posted on Wednesday, May 26, 2010 6:17:43 PM (Central Daylight Time, UTC-05:00)  #    Comments [13]