Transforming WinForms Camera control to WPF in MVVM style

 

WHY MVVM

Winforms technology enjoyed its dominance until Windows Presentation Foundation (WPF) made an entry and completely over took this legacy technology. It is now the preferred choice for developing the enterprise scale apps for desktops. It was an easy decision for companies to migrate their existing winforms code by doing simply copy and paste option. As most of the code behind written in winforms would just run in WPF, obviously the UI needs to be redeveloped. But that would defy the purpose of using the rich technology of WPF which supports data binding and eye catching glossy UI. Moreover if you are developing in WPF and are not adapting to the MVVM pattern then you are committing a serious crime. Eventually your app will grow and it would get nightmares for maintaining it.

In this blog post I talk about how I converted existing Winform Camera Control and encapsulated its entire functionality in the WPF User control so it can be reused across the project.

GETTING STARTED

Just let me introduce to you about the functionality of this project. There should be live streaming from the webcam in your application and the user should be able to take the snapshot of the on going frame. The image should be saved in users Pictures library folder. Quite a simple requirement and there are tons of samples out there which can help us to nail this problem, but all those solutions violates the MVVM pattern. My solution follows the MVVM pattern religiously and still achieves the desired functionality.

I’m using Aforge framework to capture the camera output stream. This is quite extensive framework which does more than image processing. You can get more info by reading its documentation.

Create a new WPF application. Download MVVM Light toolkit libraries from the Nuget. Now add the Aforge libraries. You would require the following

  • AForge.Controls
  • AForge.Video
  • AForge.Video.DirectShow

Please note that all these above Aforge libraries can also be obtained from the Nuget.

Now comes the two important assemblies that you would require to reference in your project and they are

  • WindowsFormsIntegration
  • System.Windows.Forms

These two assemblies allow us to integrate winform controls in xaml. You can virtually use any winform control via these assemblies. Just nest it under the WindowsFormHost and you are done.

I LOVE XAML

XAML and MVVM are made for each other. One of the cool features of any XAML based technologies is rich data binding. This feature allows us to bind any visual element. The only prerequisite for data binding is that the property to which you are binding should be a dependency property.

You can also create your own dependency properties of the user control and program it to the way you want. Create a new folder in your project and name it to ‘Controls’. Add a new UserControl to this folder and name it AForgeWebCam.xaml. Copy the below code in it.

  1. <UserControl x:Class="WPFWebCamMVVM.Controls.AForgeWebCam"
  2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
  5.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008&quot;
  6.              xmlns:aforge="clr-namespace:AForge.Controls;assembly=AForge.Controls"
  7.              mc:Ignorable="d"
  8.              d:DesignHeight="300" d:DesignWidth="300">
  9.     <StackPanel>
  10.         <WindowsFormsHost Margin="10" Name="WinFormHost" Background="{x:Null}" Width="640" Height="480">
  11.             <aforge:VideoSourcePlayer x:Name="VideoPlayer" Size="640,480" />
  12.         </WindowsFormsHost>
  13.         </StackPanel>
  14.         
  15. </UserControl>

Switch to the code behind of this user control , where we would create all the required dependency properties. We would require following dependency properties.

1)AvailableCameraSources : This will list down all the attached camera with the device name and unique id. This property will be of type IList<DeviceInfo>. The DeviceInfo is a simple class with two properties.

  1. public class DeviceInfo
  2.     {
  3.         /// <summary>
  4.         /// Gets or sets the display name.
  5.         /// </summary>
  6.         /// <value>The display name.</value>
  7.         public string DisplayName
  8.         {
  9.             get;
  10.             set;
  11.         }
  12.  
  13.         /// <summary>
  14.         /// Gets or sets the usb string by which OS identifies the hardware.
  15.         /// </summary>
  16.         /// <value>The usb string.</value>
  17.         public string UsbString
  18.         {
  19.             get;
  20.             set;
  21.         }
  22.     }

 

  1. public static readonly DependencyProperty AvailableCameraSourcesProperty =
  2.             DependencyProperty.Register(
  3.                 "AvailableCameraSources",
  4.                 typeof(IList<DeviceInfo>),
  5.                 typeof(AForgeWebCam),
  6.                 new PropertyMetadata(GetCameraSources())); //set the default value

Have a look at line number 6 in the above code , the last argument of dependency property is PropertyMetaData , whose one constructor accepts one parameter Object type. Using this parameter the developer can set the default value of the dependency property. So here I initialize this property by calling private static method GetCameraSources. This constructor also accepts the other arguments which I will explain later.

  1. private static IList<DeviceInfo> GetCameraSources()
  2.         {
  3.             availableCameraSources = new List<DeviceInfo>();
  4.             var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
  5.             foreach (FilterInfo filterInfo in videoDevices)
  6.             {
  7.                 availableCameraSources.Add(
  8.                     new DeviceInfo { DisplayName = filterInfo.Name, UsbString = filterInfo.MonikerString });
  9.             }
  10.             return availableCameraSources;
  11.         }

2)CameraId : This is of string type . The value is basically the unique id of the camera by which the operating system identifies it. This is used by AForge VideoSourcePlayer control to render the video streaming.

  1. /// <summary>
  2.       /// The camera id property.
  3.       /// </summary>
  4.       public static readonly DependencyProperty CameraIdProperty =
  5.           DependencyProperty.Register("CameraId", typeof(string), typeof(AForgeWebCam), new PropertyMetadata(string.Empty, OnCameraValueChanged, OnCameraCoherceValueChanged));

Notice the two call-back methods OnCameraValueChanged and OnCameraCoherceValueChanged.The first call back methods handles the starting and stopping of the camera.The coerce call-back method allows us to adjust the value if of the property if it is not within the required range and throwing exception.

  1. private static void OnCameraValueChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
  2.       {
  3.           host = (AForgeWebCam)dependencyObject;
  4.           if (e.NewValue == null || string.IsNullOrEmpty(e.NewValue.ToString()))
  5.           {
  6.  
  7.               StopVideoDevice();
  8.               return;
  9.           }
  10.  
  11.  
  12.           if (e.NewValue != e.OldValue)
  13.           {
  14.               if (videoDevice != null)
  15.               {
  16.                   StopVideoDevice();
  17.                   InitVideoDevice(e.NewValue.ToString(), (AForgeWebCam)dependencyObject);
  18.               }
  19.               else
  20.               {
  21.                   InitVideoDevice(e.NewValue.ToString(), (AForgeWebCam)dependencyObject);
  22.               }
  23.           }
  24.       }

 

  1. private static object OnCameraCoherceValueChanged(DependencyObject dependencyObject, object basevalue)
  2.         {
  3.             host = (AForgeWebCam)dependencyObject;
  4.             if (string.IsNullOrEmpty(basevalue.ToString()))
  5.             {
  6.                 return null; // if basevalue is null then return
  7.             }
  8.  
  9.             if (availableCameraSources.FirstOrDefault(c => c.UsbString.Equals(basevalue.ToString())) == null)
  10.             {
  11.                 // check if the basevalue exists in the availableCamerasources , if not then assign the first value of the availableCameraSources
  12.                 if (availableCameraSources != null)
  13.                 {
  14.                     var firstOrDefault = availableCameraSources.FirstOrDefault();
  15.                     if (firstOrDefault != null)
  16.                     {
  17.                         return firstOrDefault.UsbString;
  18.                     }
  19.                 }
  20.             }
  21.  
  22.             return basevalue;
  23.         }

3)TakePictureCommand : This property is of ICommand type. And its default value is set to TakeInteralPictureCommand private property. The action of this command encapsulates all the logic of taking the picture. A thing to note over here is that Aforge framework does not provide this functionality out of the box. I have written the custom code to achieve this. I capture the position of the control and using the apis available in System.Drawing namespace I create new image and save it to the pictures folder. See the code below

  1. public static readonly DependencyProperty TakePictureCommandProperty =
  2.             DependencyProperty.Register(
  3.                 "TakePictureCommand",
  4.                 typeof(ICommand),
  5.                 typeof(AForgeWebCam),
  6.                 new PropertyMetadata(TakeInternalPictureCommand));

 

  1. private static void TakePicture()
  2.         {
  3.             try
  4.             {
  5.                 const int PanelWidth = 640;
  6.                 const int PanelHeight = 480;
  7.                 string fileName;
  8.  
  9.                 System.Drawing.Point pnlPoint =
  10.                     host.VideoPlayer.PointToScreen(
  11.                         new System.Drawing.Point(host.VideoPlayer.ClientRectangle.X, host.VideoPlayer.ClientRectangle.Y)); // get the position of the VideoPlayer
  12.                 using (var bmp = new Bitmap(PanelWidth, PanelHeight))
  13.                 {
  14.                     using (var g = Graphics.FromImage(bmp))
  15.                     {
  16.                         // generate the image
  17.                         g.CopyFromScreen(
  18.                             pnlPoint, System.Drawing.Point.Empty, new System.Drawing.Size(PanelWidth, PanelHeight));
  19.                     }
  20.  
  21.                     // Get MyPictures folder path
  22.                     fileName = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) + "\\"
  23.                                + DateTime.Now.ToString().Replace(":", string.Empty).Replace("/", string.Empty) + ".jpg";
  24.  
  25.                     // save the file
  26.                     bmp.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);
  27.                 }
  28.  
  29.                 MessageBox.Show("Picture saved in Pictures library with filename=" + fileName, "Success");
  30.             }
  31.             catch (Exception exception)
  32.             {
  33.  
  34.                 MessageBox.Show(exception.Message);
  35.             }
  36.         }

 

CODE REUSE

The whole idea of wrapping up the entire camera functionality in the UserControl was the code reuse. This control can be now dropped into any xaml window, page or even other user control.

 

  1. <Window xmlns:Controls="clr-namespace:WPFWebCamMVVM.Controls"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4.         xmlns:Helpers="clr-namespace:WPFWebCamMVVM.Helpers" x:Class="WPFWebCamMVVM.MainWindow"
  5.         Title="MainWindow" Height="350" Width="525">
  6.     
  7.     <Window.Resources>
  8.       
  9.         <Helpers:DeviceInfoConverter x:Key="DeviceInfoConverter"/>
  10.         </Window.Resources>
  11.     <Window.DataContext>
  12.         <Binding Mode="OneWay" Path="Main" Source="{StaticResource Locator}"/>
  13.     </Window.DataContext>
  14.     <Grid>
  15.         <Grid.RowDefinitions>
  16.             <RowDefinition Height="Auto"/>
  17.             <RowDefinition Height="Auto"/>
  18.             <RowDefinition Height="Auto"/>
  19.             <RowDefinition Height="Auto"/>
  20.             <RowDefinition Height="Auto"/>
  21.             <RowDefinition Height="Auto"/>
  22.         </Grid.RowDefinitions>
  23.         <ComboBox x:Name="ComboBox" Grid.Row="0" Margin="10" ItemsSource="{Binding AvailableCameraSources,ElementName=WebCam}" DisplayMemberPath="DisplayName" SelectedItem="{Binding SelectedDevice}"/>
  24.         <!–Displaying the camera stream using the element binding–>
  25.         <TextBlock Grid.Row="1" Text="{Binding SelectedItem, Converter={StaticResource DeviceInfoConverter}, ElementName=ComboBox}" x:Name="UsbString" Margin="10"></TextBlock>
  26.         <Controls:AForgeWebCam x:Name="WebCam" Grid.Row="2" Margin="10" CameraId="{Binding SelectedItem, Converter={StaticResource DeviceInfoConverter}, ElementName=ComboBox}" />
  27.         <!–Comment the above two lines and Uncomment the below line if you want to assign the cameraUSB property from viewModel–>
  28.         <!–<Controls:AForgeWebCam x:Name="WebCam" Grid.Row="2" Margin="10" CameraId="{Binding CameraUsbId}" />–>
  29.         <Button Margin="10" Grid.Row="3" Command="{Binding ConnectCommand}">Connect</Button>
  30.         <Button Margin="10" Grid.Row="4" Command="{Binding TakePictureCommand, ElementName=WebCam}">Take Picture</Button>
  31.         <Button Margin="10" Grid.Row="5" Command="{Binding DisconnectCommand}">Disconnect</Button>
  32.     </Grid>
  33. </Window>

Using the element data binding capabilities I have binded the Combo box. So as a developer who is consuming your control does not have to bother about getting the camera sources because your control already exposes that as a dependency property.

The api of the usercontrol is quite simple , to connect to the camera set the CamerId property to the valid connection string, to disconnect it make it null or set the property to empty string.

 

CLOSURE

Using WinFormHost control in WPF lot of existing controls can be reused. The only challenge lies how you ensure that your MVVM design in not getting compromised with this implementation. If planned smartly then this can be taken care off. I hope you must have enjoyed the reading this article. Please leave your valuable feedback in the comments. Download the sample code from here.

Advertisements

Implementing INotifyPropertyChanged in C#5.0 way

 

All XAML developers are well aware of INotifyPropertyChanged interface. This interface is key to the data binding. Every ViewModel class or ViewModelBase abstract class implements this interface. One of the biggest issue with it is that the PropertyChangedEventHandler delegate event argument, PropertyChangedEventArgs constructor accepts the property name as string value. This can introduce bug in your code because of “MAGIC STRINGS” , where by which if developer misspell the property name or you require to rename your property , then it should be done very carefully otherwise your data binding can go completely for a toss and you would go in circles to figure out what the issue is. Let me illustrate what I am talking about with the code snippet below.

Old way implementation
  1. public class CustomerViewModel : INotifyPropertyChanged
  2.     {
  3.         private string customerNameValue = String.Empty;
  4.         private string phoneNumberValue = String.Empty;
  5.  
  6.         public event PropertyChangedEventHandler PropertyChanged;
  7.  
  8.         private void NotifyPropertyChanged(String propertyName)
  9.         {
  10.             if (PropertyChanged != null)
  11.             {
  12.                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  13.             }
  14.         }
  15.  
  16.         public string CustomerName
  17.         {
  18.             get
  19.             {
  20.                 return this.customerNameValue;
  21.             }
  22.  
  23.             set
  24.             {
  25.                 if (value != this.customerNameValue)
  26.                 {
  27.                     this.customerNameValue = value;
  28.                     NotifyPropertyChanged("CustomerName"); //Magic strings
  29.                 }
  30.             }
  31.         }
  32.  
  33.         public string PhoneNumber
  34.         {
  35.             get
  36.             {
  37.                 return this.phoneNumberValue;
  38.             }
  39.  
  40.             set
  41.             {
  42.                 if (value != this.phoneNumberValue)
  43.                 {
  44.                     this.phoneNumberValue = value;
  45.                     NotifyPropertyChanged("PhoneNumber"); //Magic strings
  46.                 }
  47.             }
  48.         }
  49.     }

In this short post I will talk about how you can avoid using these magic strings by using one of C# new 5.0 feature named as CallerMemberName attribute with support of optional parameters. So let us do some code refactoring in the above code and remove these magic strings. Have a look at the code snippet below.

New way implementation
  1. public class CustomerViewModel : INotifyPropertyChanged
  2.     {
  3.         // These fields hold the values for the public properties.
  4.         private string customerNameValue = String.Empty;
  5.         private string phoneNumberValue = String.Empty;
  6.  
  7.         public event PropertyChangedEventHandler PropertyChanged;
  8.  
  9.         private void NotifyPropertyChanged([CallerMemberName]
  10.                                            String propertyName = "")
  11.         {
  12.             if (PropertyChanged != null)
  13.             {
  14.                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  15.             }
  16.         }
  17.  
  18.         public string CustomerName
  19.         {
  20.             get
  21.             {
  22.                 return this.customerNameValue;
  23.             }
  24.  
  25.             set
  26.             {
  27.                 if (value != this.customerNameValue)
  28.                 {
  29.                     this.customerNameValue = value;
  30.                     NotifyPropertyChanged(); //Look ma no magic strings
  31.                 }
  32.             }
  33.         }
  34.  
  35.         public string PhoneNumber
  36.         {
  37.             get
  38.             {
  39.                 return this.phoneNumberValue;
  40.             }
  41.  
  42.             set
  43.             {
  44.                 if (value != this.phoneNumberValue)
  45.                 {
  46.                     this.phoneNumberValue = value;
  47.                     NotifyPropertyChanged(); //Look ma no magic strings
  48.                 }
  49.             }
  50.         }
  51.     }

Just have a look at NotifyPropertyChanged method in the above code snippet. This method argument is decorated with CallerMemberName attribute. This will replace the property name in the set accessor of that property. So you don’t need to hardcode any property name.

On the closing note I would also like to say that this is not the only way you can avoid the MAGIC STRINGS in the method name. If you are fan of functional programming like me 😉 and have some knowledge of generics you can use Linq Expressions to achieve the same. Let us see one more code snippet which does this.

Smart way implementation
  1. public class CustomerViewModel : INotifyPropertyChanged
  2.     {
  3.         // These fields hold the values for the public properties.
  4.         private string customerNameValue = String.Empty;
  5.         private string phoneNumberValue = String.Empty;
  6.  
  7.         public event PropertyChangedEventHandler PropertyChanged;
  8.  
  9.         private void NotifyPropertyChanged<T>(Expression<Func<T>> expression)
  10.         {
  11.             var lambda = (LambdaExpression)expression;
  12.             MemberExpression memberExpr;
  13.             var body = lambda.Body as UnaryExpression;
  14.             if (body != null)
  15.             {
  16.                 var unaryExpr = body;
  17.                 memberExpr = (MemberExpression)unaryExpr.Operand;
  18.             }
  19.             else
  20.             {
  21.                 memberExpr = (MemberExpression)lambda.Body;
  22.             }
  23.             if (PropertyChanged != null)
  24.             {
  25.                 PropertyChanged(this, new PropertyChangedEventArgs(memberExpr.Member.Name));
  26.             }
  27.         }
  28.  
  29.         public string CustomerName
  30.         {
  31.             get
  32.             {
  33.                 return this.customerNameValue;
  34.             }
  35.  
  36.             set
  37.             {
  38.                 if (value != this.customerNameValue)
  39.                 {
  40.                     this.customerNameValue = value;
  41.                     NotifyPropertyChanged(() => CustomerName);
  42.                 }
  43.             }
  44.         }
  45.  
  46.         public string PhoneNumber
  47.         {
  48.             get
  49.             {
  50.                 return this.phoneNumberValue;
  51.             }
  52.  
  53.             set
  54.             {
  55.                 if (value != this.phoneNumberValue)
  56.                 {
  57.                     this.phoneNumberValue = value;
  58.                     NotifyPropertyChanged(() => PhoneNumber);
  59.                 }
  60.             }
  61.         }
  62.         }

As seen this is also cool way of avoiding the magic strings by using linq expressions. Finally a quick tip always create the base class (ViewModelBase) and encapsulate all the required functionalities in it. Then all your viewmodel classes must inherit this ViewModelBase class.

Hope you must have found this post useful. Please leave your valuable feedback in the comments section.

How to work with Hierarchal data in Entity Framework

INTRODUCTION

A couple of years back I blogged about how to retrieve the hierarchical data using T-SQL features. You can read that blog post here. Today life brought to me the same cross roads and I decided to take new route , so instead of using the T-SQL approach I preferred to go towards the Entity Framework. Microsoft has recently done some great enhancements in this data access framework especially with the release of version 4.1 , you can also take the advantage of code first approach. In this post I show you how you can get hierarchal data from your database using Entity Framework. So let us get started.

GETTING STARTED

In this post I am using the same example which I used for my earlier post. We have same employee table but this time it is self referencing table. The EmployeeId column, which is the primary key in the table is referencing to the ManagerId column (Allow null is set to true) in the same table. See the screen shot below.

Self referncing Employee table

The following is the sample data in this table

Employee table data

In the above screen shot you must observe that the ManagerId for the first row is null, which means this is the root in the hierarchy.

So now when you import this table into your model using the Entity Framework wizard , as this is self referencing table the wizard will create two navigational properties called Employee1 and Employee2 respectively. Refer to the screen shot below.

InitialModel

These two properties does not make any sense to the developers, so let us try to rename it. Right click on the Employee1 property and select properties from the context menu. In the properties window you will see that the multiplicity is set to multiple, which means that the association is of Many type. Check out the screen shot below.

Employee1 property

In the same manner let us also rename Employee2 property , if you right click this property and see the properties window you will find that multiplicity of this column is set to 0..1 , which means that the association end can be null or one. We will rename this column to Manager as seen in the screen shot below.

Employee2

Let me explain you further about the database relationships. Any relationship in the database has three characteristics.

  1. Degree : is the number of entity types that participates in the relationship. Unary and Binary relationship are most common.
  2. Multiplicity : is the number of entity types on each end of the relationship. Few examples are 0..1 (zero or one), 1 (one) and * (many).
  3. Direction : This can be unidirectional or bidirectional

In our example Degree is of unary type , as only Employee entity is involved in the relationship. Multiplicity is 0..1 and * and direction is bidirectional.

I hope that the above discussion have cleared your concepts about the database relationships, let us see now some code which displays the hierarchal data.

 Code

The above code loops through employee entity and checks whether the manager property is null and based on that writes the output . See the output for this code below.

ProgramOutput

CLOSURE

Anything new that comes out from Microsoft stable excites me. I always make a point to utilize the new technology whenever I get new project or opportunity. This blog post was also the result of the same passion. I encourage developers to keep the learning passion always alive because if that dies then consider your career to be finish. Let me know your thoughts on it in the form of comments.

KEEP LEARNING

How to add Computed Properties in WCF Ria Services on client

 

Customers have become very demanding these days, but thanks to the technology that we can satisfy them. I met one of our clients for the new project. The project was complex in the sense that it involved lot of calculations. The prime requirement of the client was that the end user must immediately see the output of the calculations once all the required input is provided by them. My first choice for any LOB apps is Silverlight 4 + WCF Ria services. So the big question was that how can I get this done. After doing a bit research I found out that it was pretty straight forward with WCF Ria Services framework. So here we go I will outline the solution with sample scenario.

The scenario is pretty simple. We have customer Entity mapped to Customer table in the database. Following are its columns.

  • FirstName
  • LastName
  • DateOfBirth

Now here is the twist we need to calculate the Age of the customer. As this property needs to be computed we don’t have it in our database but this should be calculated after user enters date of birth. So to accomplish this follow the steps mentioned below

  1. Add a new partial  class  of the same name in your client project. Please ensure that this class namespace is same as your Domain Service namespace.
  2. This class must be inherited from the Entity class available in System.ServiceModel.DomainServices.Client namespace.
  3. Add a read only property “Age” of integer type. Write your age calculation logic in the get block of this property.
  4. Raise the property event when the DateOfBirth property is changed.

ComputedPropertyCode

Hope you would find this useful. Awaiting your valuable feedback.

Cheers

Silverlight enabled WCF service deployment on IIS

 

INTRODUCTION

I just completed one of my Silverlight 4 project. In this project I used Silverlight Enabled WCF service for handling my database operations. As the project requirements was just to read the data from the database via stored procs and display it on the datagrid. I intentionally didn’t use WCF RIA services as I thought this would be an overhead for this type of requirement. Both WCF Ria service (Domain Service) and Silverlight enabled WCF service works on the core principles of WCF technology. The difference is that lot of code is generated by Ria Services framework and there is no physical .svc file in your project whereas in the Silverlight enabled WCF service you have .svc file with you and things are more under your control. Both supports Asynchronous service operations. Besides this when you add a service reference to your Silverlight project from the solution a new file called “ServiceReferences.ClientConfig” is also created which plays key role, read further.

THE DEPLOYMENT GOTCHAS

The solution worked like a gem in my Visual Studio 2010 development environment , which uses Cassini web server. But when it came to deployment on IIS , I ran into issues. As usual the server returned the infamous error “NOT FOUND” to Silverlight client. I was already aware of RIA deployment problems and I tried all those steps but all in vain. Then Fiddler came to my rescue. This is awesome http debugging tool and I really love it. After analysing the fiddler output I was shocked that my .svc url was still pointing to the localhost. Holy crap what is that I was totally lost and didn’t know what was happening. Though my address attribute in the endpoint element of web.config file was pointing to the correct path of my IIS virtual directory, then where did I go wrong.

SOLUTION

I didn’t gave up so easily , I started digging out forums , googling , binging whatever you can add over here. But could not find anything concrete which could solve this issue. Then Visual Studio intellisense helped me. I came to know that the proxy service class that was generated by Visual Studio has more than one constructor, five to be precise. The third constructor which accepts the two parameters endpointConfigurationName and remoteAddress. See the below screen shot.

VS2010 Intellisence

From the code you can see it was matter of two lines which made me rest in peace. The code is pretty self explanatory. I declare the objUri variable and initialize with .svc path. As mentioned earlier here we have physical .svc file present and this should be also deployed on IIS. The Application.Current.Host.Source returns you the .xap file path and as my .svc file was located in the root of virtual directory I used ../ and the .xap file was located in the ClientBin folder. The second line of the code does the magic. Here I have used the endpointConfigurationName from the ServiceReferences.ClientConfig file. Remember what I told in the beginning. This is a string value which is auto generated by Visual Studio and finally the second parameter is fully qualified path of service file. After making these changes I rebuild the solution , did a deployment using Publishing Wizard and viola my application started working.

CONCLUSION

I am still in the process of finding that even though when I specified the endpoint address in the web.config file why the service was referring to my localhost. I thought that should have resolved the issue but it didn’t work. Now my address attribute in web.config is empty string and I am not require to deploy the ServiceReferences.ClientConfig file on IIS. It just simply works with these two magical lines of code. Hope this solution will help the community in their deployment issues and they don’t undergo the struggle period that I went. After all learning is all about sharing. Let me know your thoughts for the same.

Cheers

Plug-ins / Modules Development with MEF -Part II

INTRODUCTION

This is the continuation of my earlier post. I strongly encourage the readers to stop here and read the part one of this series if they haven’t read it yet. In part one we looked at the brief introduction on MEF and a practical scenario where this framework can be implemented. We talked about HRMS , I have code named it as MangoPeople :). This is not an HR solution but just peeps into it how MEF can help you to build these type of enterprise apps. So let us get jump started into it.

MEF APPLICATION

Our MangoPeople HR solution is built on WPF using Visual Studio 2010 RC in .Net Framework 4.The Visual Studio solution consists of 5 projects as shown in figure below.

solutionexplorer

  1. MangoPeopleHR : This is based on WPF Application Template. It is an empty shell and just have one Xaml Window. Look at the screen shot below which will give you the fair idea.
    MangoPeople Main Window
    On the Left hand side you will see the Modules that are available. If your client who has not purchased any of the modules , those links will not be active (You wont get an hand mouse pointer on that module link). On the Right hand side there is a content control which will hosts the main window or entry point screens of the modules selected. The output of this project is an .exe
  2. CommonStuff: This is project based on the standard windows class library project. It contains the helper class of handling commands for ViewModel and the other class has the MEF contract interface.
  3. PersonalModule:
  4. PayrollModule:
  5. RecruitmentModule:

The items 3,4 and 5 are based on WPF User Control Library Project Template whose output is the dll. I hope you must have now got the overall idea of the solution. Now the catch here is that all these modules should be pluggable. If you add them they become active and vice-versa. So to make them active you must copy the module dll into one of the designated folder, I call it MangoPeopleLic. In this folder if the module dll is present that module link will be active if removed it will be inactive. So time has come now to see the inside stuff.

MEF IMPLEMENTATION

Though these modules are independent of the main application. There should be some glue which should bind them once they are plugged in (dll is copied in the designated folder) and that is where the MEF contracts or interface comes in and play a vital role in overall MEF implementation. Let us look at the code

namespace CommonStuff
{
    public interface  IContract
    {
        string ModuleName { get; }
    }
}

The Icontract interface has only one read only property called ModuleName. Now any type that needs to expose these functionalities should be decorated with the Export attribute with typeof parameter. In our scenario all our UserControl main class or the entry points of every module should have this attribute. See the code below of one of PersonalMainView.xaml.cs

using System.Windows.Controls;
using CommonStuff;
using System.ComponentModel.Composition;

namespace PersonalModule
{
    /// <summary>
    /// Interaction logic for MainPersonalView.xaml
    /// </summary>
    ///
    [Export(typeof (IContract))]
    [ExportMetadata("ModuleName","Personal")]
    [ExportMetadata("ModuleId",1)]
    public partial class MainPersonalView : UserControl,IContract
    {
        public MainPersonalView()
        {
            InitializeComponent();
        }

        #region IContract Members

        public string ModuleName
        {
            get { return "Personal"; }
        }

        
    }
}

The above code besides inheriting the UserControl class also implement the IContract interface. It is also decorated with the Export and ExportMetaData attributes.All MangoPeopleHR modules user control classes have the same code except for the ExportMetaData attributes values and IContract interface property value. So we are done from the modules perspective and now let us jump to the MainWindowViewModel class which gets binded to the MainWindow. One of the most important property in this class is ModulesPurchased.

[ImportMany]
        public Lazy<IContract,IDictionary<string ,object>>[] ModulesPurchased  { get; set; }

This property is decorated with ImportMany attribute to load all the required composable parts also it is of Lazy type , which means the parts will be loaded on demand. Remember I talked about the glue earlier which binds the main exe with all the dll. This property is the glue here. In modules project the usercontrol classes if you remember we were using Export attribute of same contract and here we are using ImportMany attribute of the same contract. Does that make sense to you , Great !. Now let us look at the other methods which put MEF on fire.

private CompositionContainer GetLicenseInfo()
        {
            var objCatalog = new AggregateCatalog();
            var objAssembly = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
            objCatalog.Catalogs.Add(objAssembly);
            objCatalog.Catalogs.Add (new DirectoryCatalog(LicenceDirectory ));
            var container=new CompositionContainer(objCatalog );
            return container ;
        }

The above code listing does the job of adding all the parts in the repository. We use AssemblyCatalog and DictionaryCatalog. The LicenceDirectory is the class variable which stores the path of the folder where all modules dll will be there. So now we have parts in the repository so now let us compose them , the code of which is described below.

public  bool CheckLicences()
       {
           _LicenceComposionContainer = GetLicenseInfo();

           try
           {
               _LicenceComposionContainer.ComposeParts(this);
           }
           catch (Exception)
           {

               System.Windows.MessageBox.Show("Unable to Retrieve the License Information");
               return false;
           }
           return true;
       }

After getting the value of the CompositionContainer from the GetLicenseInfo method. It tries to call the ComposeParts method.Returns a boolean value dependent on this method call. And now finally let us see the Command method which enables or disables the hyperlink based on the dlls available in the License directory.

private bool  CanModuleSelectExecute(object param)
        {
            bool isAllowed=false;
            foreach (var item in this.ModulesPurchased )
            {
                if (param.ToString().Equals(item.Metadata["ModuleId"].ToString()))
                {
                    isAllowed = true;
                    break;
                }
                else
                {
                    isAllowed =false ;
                }
            }
            return isAllowed;
        }

Here we rotate in the loop and compare the param value with the metadata in the array of ModulesPurchased property. If the match is found the function returns true which will enable the link else the link will be disabled. The param parameter of object type is binded in the Xaml via CommandParameter property.

CLOSURE

So you just saw how MEF simplifies the application partitioning.Though in past we had such frameworks which provided this type of functionalities like Composite Application Blocks,PRISM and Unity to name few. But MEF is different and with ease it can be integrated. It is now the official part of the CLR, what more do you accept to understand its importance.So get started now and start using MEF. You can download the sample code of this post from here. Please ensure to change the value of LicenseDirectory variable to suit to your enviornment otherwise you will get error. Do let me know your thoughts on MEF.