Rory Primrose

Learn from my mistakes, you don't have time to make them yourself

View project on GitHub

Readable testable code

I read Patrick Smacchia’s post this morning about a simple trick to code better and to increase testability and found it to be a great argument. These are the kinds of posts that I really enjoy reading and thinking about. They often have me hacking up test projects to flesh out ideas or kicking off Reflector to see what the BCL is doing.

This was a good post because it got me to challenge why I am coding in the particular style that I have. I have always been a fan of combining if tests when it doesn’t result in overly complex logic. In this case, Patrick is arguing that such a style of coding increases nesting depth and makes testing harder.

Take this test case based on his post:

Read More

Finding the type of UIHierarchyItem.Object

I have written a few addins over the last couple of years and I have always found the object model really painful to deal with. One of the more common problems I have encountered is trying to identify the type of UIHierarchyItem.Object. This is especially common when you deal with the contents of the Solution Explorer window.

I only know of one solution for identifying the real type behind the object. You can make a call out to Microsoft.VisualBasic.Information.TypeName(Object) to attempt to resolve the type. This wasn’t always successful and was also a little limited as the object often implements multiple types. I realised that there was a very easy and more comprehensive way of figuring out what types were being implemented.

By using this DebugHelper class in your addin solution, you will be able to figure out the object types. The Conditional attribute ensures that these methods (and calls to them) will not appear in your release build. The method takes a UIHierarchyItem and searches all the publicly available types of all the assemblies in the app domain for types that are implemented by the UIHierarchyItem.Object property.

Read More

When is EnvDTE.Project not an EnvDTE.Project?

When it is a EnvDTE.ProjectItem. I must admit that this one took me by surprise.

I am writing a Visual Studio addin for launching Reflector (see the CodePlex project here). You can launch Reflector from the tools menu and the Solution Explorer window and code document context menus. This issue came about when I found a bug in my addin while doing some testing. The scenario encountered was that the binary references for projects in Solution Explorer (the Project node and References node) were not resolved. I had tested this feature in another solution successfully and noticed that the difference between the solutions was that the one with the bug had the projects in solution folders.

After doing some debugging, it turns out that when a project is contained in a solution folder, the UIHierarchyItem.Object value exposed through Solution Explorer is no longer represented by an EnvDTE.Project. It is now an EnvDTE.ProjectItem. Ironically, you must reference ProjectItem.SubProject to get access to the project.

The fact that the project is a project items sub project because its parent is a folder in Solution Explorer is totally confusing.

Read More

Lying to WCF

There are cases when you need to transmit username/password credentials to WCF without transport security. The times that you should do this are rare because of the obvious security implications of sending credentials over the wire without encryption. One case where this is required is where hardware acceleration is used in a load balancer. The traffic between the load balancer and the client is encrypted, but the traffic between the load balancer and the service host is not. The issue here is that the service still needs the credentials passed to the load balancer from the client.

Drew Marsh has a great write up about how to lie to WCF about the security of the binding that it is using for a service. Nicholas Allen has also posted on the topic here and here.

Read More

WCF Security - Getting the password of the user

A common problem with service security is that username/password security is needed for authentication and authorization at the service boundary, but those same credentials are also required to consume other resources such as a database or underlying service. By default, username/password security will run the authentication and authorization of the credentials but only the username is available to the executing service code. This is typically made available through Thread.CurrentPrincipal.Identity.Name.

Storing username password credentials in a custom principal and identity against Thread.CurrentPrincipal is a really nice way of going. Thread.CurrentPrincipal returns IPrincipal which is a common framework type that will be available to all layers of a service executed by the thread. If Thread.CurrentPrincipal.Identity can return a custom IIdentity, then this is where the password can be made available. Using Thread.CurrentPrincipal frees up business and data access layers from relying on any security design that is tied up with a specific service implementation. The trick is how to get username password information into the thread that executes the service code.

Read More

Implementing IErrorHandler

As soon as I read about IErrorHandler in Juval Lowy’s book, I was sold. This interface in WCF is excellent to use for error handling and shielding at service boundaries. The interface comes with two methods.

  1. ProvideFault allows you to handle the error and determine what is returned to the client. This is where exception shielding comes in. The service implementation or any of the layers in the service can throw an exception. The error handler is the opportunity to determine whether the exception thrown is something that the service understands and is happy for the client to receive or whether the exception needs to be shielded into another exception/fault. A shielded exception would typically be a generic service exception that says that the service encountered an error.
  2. HandleError allows you to process some error specific logic asynchronous to the service call. This means that you could do some tracing/instrumentation or some expensive operation without blocking the client call.
Read More

Code coverage doesn't like foreach loops

I have an interesting scenario that I have just come across in my code. I have a foreach loop that is not getting 100% code coverage in unit tests. Prior to this, I really liked foreach for its ease of use and readability even though there is a minor performance penalty compared to using a for loop.

Here is the situation. I have a flush method that looks like this:

Read More

Outlook has a dialog open, but it doesn't

I was playing with a new profile on my laptop last night as I was wanting to work with Outlook data syncing to my phone without changing the data on my normal profile. After I logged in, I found that Outlook wasn’t responsive. I could use the mouse to do actions, but not the keyboard. I also couldn’t close it. When I tried to add a SharePoint list Outlook would give me a message saying “A dialog is open. Close it and try again.” The great thing was that there was no dialog open.

This frustrated me insanely for 30 minutes. I then remembered something from working at a small IT company about eight years ago. Back then, we had an issue with Word automation from VB6 on a server where the account running the service hadn’t yet logged into the machine. Word was locking up on the dialog that appears asking for your name and initials. We had to log into the machine running the service with the service account, open Word, click Ok, log off and then the service would run the Word automation without a problem.

Read More

Log in form usability problem

I’ve just realised a usability problem with website log in forms. The “remember my password” checkbox is almost always below the log in button. For keyboard support, the sequence goes like this:

  1. Give focus to the username field (any good app would do this for you)
  2. Type in username
  3. Tab to focus on password field
  4. Type in password
  5. Tab to focus on the log in button (with perhaps another tab to get over a cancel button)
  6. Tab to focus on the checkbox
  7. Space to check the checkbox
  8. Shift-Tab to give focus back to the log in button with perhaps another tab if you need to skip over a cancel button
  9. Space to fire the log in button

If the forms where changed to simply have the checkbox above the log in button, then the keyboard sequence would be:

  1. Give focus to the username field (any good app would do this for you)
  2. Type in username
  3. Tab to focus on password field
  4. Type in password
  5. Tab to focus on the checkbox
  6. Space to check the checkbox
  7. Tab to focus on the log in button
  8. Space (to fire the Log in button)

This would read better as the user only traverses down the screen rather than down and then up. It removes unnecessary actions and makes more sense.

Read More

Xml comments and the include element

I have been doing a lot of work over the last week writing xml comment documentation. I have been compiling the xml output into chm files using SandCastle, SHFB and my own SHFB wrapper application. I have been increasingly been finding that I am writing remarks that I want to reuse across different methods and properties of several classes in an assembly. Today, I had a particular property scattered among several data contracts for a WCF service that are used for the same purpose and have the same xml comments.

For several days I have been doing the very bad practice of writing the documentation and copying what I need to the other locations. I remembered reading about the <include /> element for xml comments and read up on it in more detail (see here and here). After a bit of experimentation today, I can say that the <include /> element is very powerful for three reasons:

  1. You can include the entire xml comment for an item
  2. You can include part of the xml comment for an item
  3. You can include include elements and they will be recursively resolved

Lets look some examples. Here is my initial code:

Read More