My diary of software development

Archive for November, 2009

Binding updates to a WPF View from outside of its ViewModel – part 1

Application Overview

I’ve been working on an MVVM WPF app that has a view of metrics collected by some background threads.  A screen shot is shown below:

As I mentioned, I’m using the MVVM pattern for this app so I have a view, a view model, and a model layer. The model layer consists of a ThreadMetrics class which contains the metrics you see for one row of the screen shot above. The view model (ingeniously named the ThreadMetricsViewModel) contains an instance of a ThreadMetrics class as well as the necessary get accessors for the view’s binding targets. The class layout and interactions are shown below:

MVVM Class Interactions

Where this app starts to differ from the other MVVM apps I’ve written is that the updates to the view model’s data do not come from the UI user or a command handler inside the view model. Instead they start with a background thread which updates counts inside the ThreadMetrics instance within the ThreadMetricsViewModel. From there, the view binding will pick them up from Get accessors within the ThreadMetricsViewModel.

Since in this application, data is changed outside of the view model and needs to be reflected on the view, my problem became how to trigger the ThreadMetricsViewModel’s property changed events everytime the values in its associated ThreadMetrics instance were changed. There was also a problem with how often these values changed which caused the view to become unresponsive to user manipulations and I’ll cover that too. 

Triggering view model property changes from the background thread

For the first problem of triggering the property changed events, I’m using the Mediator v2 solution which allows the ThreadMetrics instance to advise the ThreadMetricsViewModel of changes to its metric counts by the background thread. Each time the ThreadMetricsViewModel handles an update notification for one of these counts, it will issue a property changed event which causes the view binding to pick up that value and update it on the view. The image below shows the interaction which solved this problem:

Triggering The ViewModel's PropertyChange Events

Triggering The ViewModel's PropertyChange Events

Keeping the view from becoming unresponsive

The next problem was that the PropertyChange events were happening so fast due to the the high rate of activity by the background threads that the UI became unresponsive. I solved this problem by only sending the PropertyChange events periodically (but often enough to keep the view continuously updated.) The image below shows the UpdateUI method which does this:
The UpdateUI Method

Summary

So that is how I handled updating the view in my MVVM app from changes made outside of the view model, but I need to say that I still don’t get a ‘good’ gut feeling from this implementation.  The ThreadMetricsViewModel doesn’t really serve any purpose other than being a go-between or a proxy to the ThreadMetrics instance which holds the actual values and the background thread class is where the actual logic takes place. It seems that there should be more logic in the ThreadMetricsViewModel, that maybe the ThreadMetrics class should go away and the background thread should reach into the ThreadMetricsViewModel instance to change values there. Or maybe that the ThreadMetrics and the background thread classes both should go away and all the thread and view model logic should occur inside the ThreadMetricsViewModel.

Causing a rift in the WPF coding space-time continuum

At the beginning of developing this app, I feared I may have caused a rift in the space-time continuum of WPF coding best practices because  I did indeed have all of the thread/view model logic and data inside the ThreadMetricsViewModel instances. However this didn’t seem right either because I knew I was mixing backend service operations with view layer operations. It seemed that mixing everything like this into only two layers: the view and view model was violating some basic law of WPF  coding best practices. I began to fear I had created an enormous rift in space and time so I refactored the logic into my current ThreadMetricsViewModel, ThreadMetrics, and background thread classes. Unfortunately it may already be too late and I’m writing this blog from another space-time realm of WPF development and do not know it.

My next post will talk about how I handled updating the aggregate metrics from all my ThreadMetrics instances. That is, the total number of Create and other operations.

Advertisements

Calling a SAS WebService from an .Net application

I finally got SAS BI Web Services for .Net installed after I received my 6th installation plan file from SAS and that odyssey is blogged here: 

Creating The SAS Web Service

I am now ready to create a simple web service on SAS and to call that web service from a .Net application. SAS web services are wrappers which are created around a SAS stored process (SP). I found some basic SAS code on the Internet and created a simple SP which took in zero parameters, did some calculations, and returned 2 strings. I then used the SAS Management console to deploy that SP as a web service named CPI1.asmx. 

SAS web services are located in an IIS virtual directory named SASBIWS. This directory contains the WebServiceMaker.asmx web service which SAS used to create my CPI1 web service and the directory contained my CPI1.asmx file. On my SAS server, this filesystem directory is located here: 

 E:\SAS\Config\Lev1\Web\Applications\SASBIWebServicesDotNet9.2\webroot 

  

Setting Up SAS Web Service Logging

I was now ready to create the .Net app to call the web service, but before I did I wanted to ensure I had as much logging turned on at the SAS server as I could get. This desire for massive quantities of log information was a direct result of the injuries I had experienced while trying to get SAS installed in the first place. Nothing in SAS is simple so I wanted to turn on logging. Thankfully I had figured out that SAS uses log4net as their logging module during my SAS installation odyssey by sifting through their .Net assemblies with reflector. If you ever need to know where this log4net config file is located, it is located here on my SAS server:  

c:\Documents and Settings\All Users\Application Data\SAS\WindowsClientLogging\log4netConfig.xml 

  

Creating A .Net App To Call The WebService

I created a console app compliled as .Net 2.0 because I have to use WSE. I don’t know if I could have used .Net 3.5 and WCF to call it but why make this more complex right now? I simply want to call the WS and get my results back. 

I called the web service and immediately got back this exception: 

System.Web.Services.Protocols.SoapHeaderException: Microsoft.Web.Services3.Secuity.SecurityFault: Security requirements are not satisfied because the security header is not present in the incoming message. 

That made sense because I wasn’t passing any credentials and surely SAS would expect them. I looked at the wse3policyCache.config located in the SASBIWS directory and found that it is expecting the security header in the SOAP package and by poking around on the web, I found I could pass that header with this code (my generated web service client proxy is named CPI1WS.CPI1):

CPI1WS.CPI1 ws = new CPI1WS.CPI1();
UsernameToken token = new UsernameToken(“
sasadm@saspw“, “Password123”, PasswordOption.SendPlainText);
ws.SetClientCredential(token);
ws.SetPolicy(“usernameTokenSecurity”);

But there was a problem because the CPI1 class derived from SoapHttpClientProtocol which did not contain a SetClientCredential() or a SetPolicy() method. I fixed this by ignoring line 6 of the auto-generated CPI1 file which states Changes to this file may cause incorrect behavior… and modifying it to derive the CPI1 class from WebServicesClientProcotol.

I executed again and this time, the call was successful and I got my results back.

WAHOO!!!! I did it!!!! I called a SAS web service from a .Net application!!!! WAHOO!!!

I’m so happy. It took me forever to get to this point. There are many more details to fill in such as using Windows integrated security to make the call rather than passing plain text credentials, but this is a major milestone and I am happy.

A New Way To Hide Disabled WPF TreeView Items

I had a project with a strange requirement which dealt with hiding disabled items on a WPF tree view. The easiest way to for me to explain this requirement is to show it to you visually rather than try to explain it in words. First, take a look at the the image below, it is of a tree view with both enabled and disabled items:

Before

Tree View Showing Enabled and Disabled Items

The strange requirement which I was having difficulty with was to hide those inactive items but still leave their active descendants visible. Notice that item 1 is disabled but it’s direct descendant item 1.1 is not.  So to corectly implement this requirement, I would need to hide the parent item 1 but leave its child item 1.1 still visible. And not only leave its child still visible but leave its child’s horizontal positioning intact as well.

Below is an image of this requirement in action. All inactive items are hidden but their active children are not. If an active item was horizontally aligned X number of device units to the right when its inactive parent was visible, then it needed to stay horizontally alligned X number of device units to the right when its inactive parent was hidden.

After

Tree View Showing Only Active Items

I was writing this project using the MVVM pattern and so in my first attempt at this requirement, I simply used some data triggers in my XAML to hide items which were marked inactive in my view model. Walla! I was done and could move onto more pressing issues in the project. But I soon realized that was not going to happen because although I was able to easily hide inactive tree view items, their children were hidden also.  The default TreeView action when hiding an item was to hide that item’s children also regardless of if the children are active or not.

In order to solve this problem and implement my requriement correctly, I knew I’d have to probably look at the TreeView’s control template and modify it. Which I was dreading. I am not a XAML expert and wanted no part with doing something like this. As a matter of fact, I was quite confused by all of those ‘templates’ in WPF I kept hearing about and trying to read about. There is a control template, a data template, an items panel template, and others. I was thinking to myself, just how many templates are there any way? Do we actually need them? Come on Microsoft, make something easy for me for once.

So after I got over my rant, which took weeks, I took the time to sit down and tell myself “I am going to do this. It will be my project for the day and I can do this.” I felt the ‘force’ close by (well actually Josh Smith’s blog but close enough) and so I felt confident.

Isn’t it strange that after you do something which had been challenging you and forcing you to struggle to surmount it, that it really doesn’t seem so difficult after you do it? I hate that feeling, it makes me feel like I didn’t do anything. Nevertheless, I am going to present the very few and simple steps that I did to accomplish this daring and heroic feat :

1 – I pulled the TreeView control template with the Show Me The Template tool and copied it into my build directory to a new file named TreeViewForStrangeRequirement.xaml.

2 – I then placed a TreeView in my window’s XAML and referenced this new template:

XAML1

3- I had a checkbox on my window which the user could check to show only the active tree view items or the user could uncheck it to show all active and inactive tree view items.

4- I modified the control template at line 139 and added a MultiDataTrigger which triggered on this checkbox and on my view model’s IsActive property for each data item. The image below shows this section of the TreeView’s control template which I modified: 

 
 
 
 
 

Template

Section of the TreeView Control Template which I modified

Figuring out why SAS BI Web Services for .Net doesn’t work – Part 3

It’s been well over a week since I wrote about battling the SAS BI Web Services for .Net beast and a lot has changed. A week or so ago I was pretty sure that I had gotten it installed and was dealing with problems created by configuration issues. I have since found out that I did not have it installed correctly and through the course of the last 10 days SAS sent me 3 additional plan files, the last of which still didn’t work correctly.

I’ll recap what I’m doing. I’m trying to get SAS BI Web Services for .Net installed and working so that I can work on the bigger picture of my project which is to document how to call these web services from a .Net web application. Installing SAS is like building the bay bridge from a bucket (a really big one) of nuts and bolts and cables and other stuff. The full installation for all of the SAS components encompasses dozens and dozens of CDs. So you install SAS in almost any permutation of components but the specific permutation which I need is the one which enables me to use SAS BI Web Services for .Net. The ‘plan’ file which I spoke of above is basically the blueprint to the bridge. It is an XML file which is fed into the SAS installer to tell it which components to install in what order and how to configure them.

Dissecting a SAS installation plan file

I’m still trying to get a working plan file from SAS. I have a ticket open with them to get a plan file with which I can install SAS BI Web Services for .Net plus all the other needed components. But to date, I haven’t received a working plan file. I am now in receipt of the 5th plan file but it doesn’t work and so I’m currently awaiting the 6th one. SAS does not support user modifications of a plan file, they only support plan files from SAS Support or a dedicated account rep. Well, I don’t have a dedicated account rep and I’m still waiting on a good plan file from SAS so last week I set about creating my own. And I succeeded. But I’m not telling SAS because with all of the complexity of SAS, I may have missed something so I’m going to wait on a blessed and ordained plan file from SAS rather than my own creation.

I took a look at the XML plan file to see what it looked like and I found that the plan file’s contents really don’t look that complicated; there are 3 basic types of information in it:

  1. Component section. These are sections which identify a component (e.g. SAS Web Infrastructure Client) and give it a unique ID within the plan file.
  2. The properties section of a component section. Properties are sequentially numbered within the whole plan file so if a new component section is inserted; all properties in the entire file need to be renumbered. These properties for the most part have identical names and values between sections. There are a couple of components which have different props but overall, they’re the same for each component section.
  3. References to other components. This seems to be the way dependencies between components are defined. Here is an example of the first 3 types of information:
    1. Plan1
  4. Some components are hierarchically children of other components. I *think* that is because the parent component is dependent on the child but then again, number 3 above seemed to indicate.  Here is an example:
    1. Plan2

I now have a working installation of SAS BI Web Services for .Net but, like I said, I’m keeping my ticket open with SAS until I get an official one from SAS because I probably missed something.

Setting up Wireless 802.1x

I am in the process of setting up 802.1x wireless security at my church. I manage my church’s network as a personal charitable effort and until recently, the church had a single flat network segment with servers and wired/wireless workstations on the same segment. They had wireless setup without requiring any type of WPA or other security so that visiting ministers could jump on and get out to the Internet.

I definitely didn’t like the fact that guest users could be on the same network as the servers and the church staff’s workstations so I sat down to think about the best way to work this out. The church wanted to keep the guest wireless because it was much easier for them when guests needed access to the Internet. However they also listened to me when I told them how much of a bad idea it was to mix their private and guest networks.

The first thing I did was to physically seperate the networks. This phase is almost done, I still need to run some cabling from the sanctuary over to the offices which are in a seperate building so that I can install guest and private wireless in the sanctuary. But the office and Sunday School areas are seperated now and I’ve placed WPA2 security on the private network to secure it.

My next phase was to implement wireless 802.1x, so  I went through the purchase requisitions to get the Windows OS upgrades (they were still at Windows 2000) and implement a 2008 domain and PKI. I then read this article: http://technet.microsoft.com/en-us/library/cc771455(WS.10).aspx, followed the instructions, and after completing them, thought I was ready to test and see if it worked. But of course it didn’t. I have never done anything this complicated that actually worked the first time, no matter how methodically I followed the instructions. It seems like I’d know by now but I really thought this would work the first time.

Since then, my work has increased and this became too much to juggle. I knew that at least we had a seperate guest and private network so I chose to put this on hold for a bit.

In the last week, I’ve had some relief from the work projects so that I have extra time in the evening and my attention has been turning back to this 802.1x project at my church. I figured this time I’d setup a Vista workstation as a sort of lab for testing this wireless auto-connecting project.