Thursday, September 6, 2012

Integration Executive Overview

In the past I was asked to provide a brief executive overview of the state of integration efforts with a vendor's product. I felt that it was an honest, objective analysis so am sharing it here, with some parts redacted. I only had a few hours to put it together so admittedly it is a little unpolished.

Integration Lessons Learned

  1. Overview
    [Vendor] grudgingly acknowledges that ACME Corporation (ACME) has, over the course of many years, created an expansive codebase that extends the capabilities of the [Application] product. There is an opportunity cost associated with the primitive design of the integration as it stands at this time. That cost is derived from the friction of attempting to integrate with a system that is not meant to be extended.
  2. What's good?
    There are a couple of places where [Vendor] gets it right.

    • HL7 – there are a few places in [Application] that allow import and export of data in the HL7 data exchange format
    • Custom reports – [Application] allows a certain degree of customization of reports, though not all features of the toolset are available
    • Overall, the amount of integration done by [ACME] developers and consultants is impressive when you consider the simple fact that [Application] isn’t meant to be extended. Regardless, a key part of our day to day operations are based solely upon the hard work and diligence of those who had to discover how to extract information from [Application].
  3. What's bad?
    There are profound consequences to the integration choices that were made.

    • Our code is intimately connected to [Application] database, which in software development is known as ‘tight coupling’. What this means is that the slightest change [on the part of Application] can break our codebase, requiring inefficient emergency patch releases [on ACME's part] to keep everything running. Even more insidious is a change that we can’t detect because of its subtlety- think of the ‘Butterfly Effect’ here. Either way, our company is at a disadvantage because we are scrambling to resolve support issues rather than creating value.
    • Rather than a single source of truth, multiple parties over the years have hooked into the [Application] database. Each group might use and interpret the data differently. This also creates more opportunity cost because of the multiple points of failure. The Master Data Management project is a step in the right direction to unify enterprise data.
  4. What's the solution?
    Integration code should have as loose a connection as possible to its target. A metaphor to describe this is the electrical cord for a lamp. When you buy a lamp, do you connect it directly to the home wiring? Of course not- what if you want to move the lamp to a new location? We all know that there is a plug that fits a standard sized outlet. So how do we ‘plug in’ code to another party’s application?

    An Application Programming Interface (API) is a public access point for integration- the electrical outlet from our earlier lamp metaphor. It’s the way that entities can exchange information without being married to one another. Think of the current titans of the internet: Google, Facebook, Amazon, Netflix, and Twitter to name a few. Surely you have used a website or mobile app that displayed information from one of these companies. This third-party integration doesn’t occur by hooking directly into Facebook’s databases- it happens through their public API’s. (See Examples section below.)

    As your set of API’s starts to grow, you start to become concerned with enterprise architecture, which is the practice of reducing complexity and cost while increasing agility by rationally and efficiently connecting systems. There are a number of ways to approach this design, and all are beyond the scope of this document.
  5. The Future
    As new systems are purchased their vendors should be questioned as to the presence of an API. Keep in mind that an API isn’t a right- it’s a privilege. Some vendors probably don’t want customers to have access to their data because they see the opportunity for profit in costly customizations. As our ability to internally disseminate data in a more modern fashion evolves, unused features of tools that we use every day become valuable. For example, Microsoft Power Pivot allows Excel users to consume data from a variety of sources and perform high-level business intelligence operations from their desktop.
  6. Examples
    Facebook API
    Google API
    Twitter API
    Amazon API
  7. Reference
    Why You Might Need an API
    APIs: A Strategy Guide
    A Comparison of the Top Four Enterprise-Architecture Methodologies

Thursday, August 16, 2012

I Feel Like I'm Taking Crazy Pills: Ninject, SignalR, and Nuget

"Could not load file or assembly 'Ninject, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference."

After 3 hours of wrestling with this error I have solved the problem but don't understand the solution. Maybe it is so blindingly obvious that I am overlooking it. As you can see from the video link below, however, this one really confused me.



Clearly there was an outdated reference in one of the three projects that comprised my prototype ASP.NET MVC 3 solution that was using Ninject and SignalR. I checked, double-checked, triple-checked references manually as well as in NuGet and everything seemed in order.

I noticed that one of my projects had an 'orphaned' NuGet packages.config file. This file had entries for Ninject and Ninject.Extensions.Conventions, but the project didn't actually have references to these assemblies.
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Ninject" version="3.0.1.10" targetFramework="net40" />
  <package id="Ninject.Extensions.Conventions" version="3.0.0.11" targetFramework="net40" />
</packages>
I like to keep my projects lean and clean so I decided to tidy up. Rather than manually deleting the orphaned file, I decided to use Nuget, thinking that this might be a more thorough approach. After NuGet was finished I tried running the solution again, though I had zero expectations that the problem was solved.

I almost fell out of my office chair when the app started up successfully.

"What in tarnation changed?" I wondered. (I didn't actually use the word 'tarnation', but hopefully you get a sense of my surprise and bewilderment.) So...to the Pending Changes window!



I was surprised to see that something had changed with the web.config file. Running a diff on the file revealed why my application had suddenly started to behave:binding redirection.



So that's it for now. Ninject and SignalR both work in harmony. I normally don't like to let mysteries like this linger unsolved, but I've got more important things to do today. (Visual Studio 2012 and Windows 8 are both available today, don't you know?)

Friday, July 20, 2012

Windows 7 dual monitor wallpaper tiles in the wrong direction

The other day I got sucked in by Lifehacker's Wallpaper Wednesday. One thing led to another and I downloaded a relaxing lake scene that would stretch across my two 23" monitors.

Before
However, once I selected my new desktop image I noticed a problem. See the majestic trees on the left monitor? They're supposed to be on the far right of the right monitor, which is also the main display monitor. This is certainly a problem.
I futilely tried altering the monitor configuration in 'Control Panel\Appearance and Personalization\Display\Screen Resolution' but that never got the results that I wanted. Updated display drivers in case there was a software solution but that didn't solve the problem either.

I knew that my monitor-spanning image's 'Picture position' had to be set to tile in 'Control Panel\Appearance and Personalization\Personalization\Desktop Background' so I did some searching using terms such as 'tiling wrong way' and tiling 'right to left' and eventually came across a post like this one that revealed the underlying issue: Windows starts drawing the image in the top left of the primary display then wraps to the other displays.

With this knowledge I realized that I was going to have to use Paint.Net to resolve the matter.

The first step was to break up my 3840 x 1080 image into two equal distinct images. Following these steps from the Paint.Net forum I was able to produce two 1920 x 1080 images.
  1. Open original source image
  2. Click on Image > Canvas Size
  3. Uncheck Maintain aspect ratio CheckBox
  4. Set pixel size to 1920 width, leaving height as is
  5. Set Anchor to Top Left
  6. Save this half of the photo, naming 'left', '1', or whatever you choose
  7. Click undo, to undo the canvas size and repeat for the right half or reopening the source image and repeat, using 'Top Right' for step 5
Now I had to combine the two images produced above into a new 3840 x 1080 image. Again, the Paint.Net forum had the answers.
  1. Open the image that you want to appear on the left monitor first
  2. Image > Canvas Size
  3. Uncheck Maintain aspect ratio CheckBox
  4. Set Anchor to Top Right
  5. Double the width (in my case I changed 1920 to 3840)
  6. Import the image that you want to appear on the right monitor by using Layers > Import From File (by default this image's anchor is top left
  7. Save this new file
After
Did it work?

Yes.

Clearly this solution is not applicable to all monitor configurations, but it should give you an idea of how to solve this problem.

Friday, June 1, 2012

Using a Func-y Dictionary Instead of a Switch

Recently I felt that the Strategy Pattern was appropriate for solving a problem. I thought that a switch statement would discriminate between the different strategies but I had reservations. I knew that the length of the switch statement would grow and become an eyesore. I had been using F# recently and had been really impressed with the succinctness of the language. These factors inspired me to find a more elegant solution to my problem.


The selection logic for each Concrete Strategy was simply to match a string value exposed as a property of a POCO. The result for each test was boolean, and a value of true indicated that a particular Concrete Strategy was to be used. I needed to somehow correlate this boolean test with an instantiated object. It occurred to me that a Dictionary<TKey, TValue> seemed to fulfill the need for this type of lookup. (Because I didn't want to unnecessarily instantiate objects, I threw Lazy<T> into the mix.)


Here is how the Dictionary is loaded:
Dictionary<Func<ITestedObject, bool>, Lazy<IStrategy>> lookup = new Dictionary<Func<ITestedObject, bool>, Lazy<IStrategy>>();

lookup.Add(o => o.Identifier.Equals("ABC-123", StringComparison.OrdinalIgnoreCase), new Lazy<IStrategy>(() => new ConcreteStrategy0()));
lookup.Add(o => o.Identifier.Equals("ABC-456", StringComparison.OrdinalIgnoreCase), new Lazy<IStrategy>(() => new ConcreteStrategy1()));
lookup.Add(o => o.Identifier.Equals("ABC-789", StringComparison.OrdinalIgnoreCase), new Lazy<IStrategy>(() => new ConcreteStrategy2()));

Here is how I use it. In my case I need to test whether members of an IEnumerable<ITestedObject> all have the same Identifier value. If all of the tested items have the same Identifier, which is determined by the use of the Dictionary's key as the predicate in the 'All' call, then I get the Value from the appropriate Dictionary entry. (Note that the object returned is Lazy<IStrategy>, and I'll have to get the actual Concrete Strategy through a call to Lazy<T>.Value.) Specifically:
var concreteStrategy = lookup.FirstOrDefault(d => someResult.TestedObjects.All(d.Key)).Value;

There is certainly room for refinement and improvement, but this solution worked well for me.

Friday, March 16, 2012

Mass assignment vulnerability references

I am a fan of ASP.NET MVC. I am also a fan of security. The two posts below combine those interests by describing how to mitigate mass assignment vulnerabilities. I am posting these so that my team can refer to them in future if needed.

Here's a bonus link. I can never remember this syntax: How to join two collections with LINQ

Monday, March 12, 2012

remove web transform files

Today I am sharing the process that I used to remove web.config transforms after a build. I wish that I could claim that I was able to implement this in a knowledge vacuum, but I had some help. As you can see, all I am doing is creating a list of all files not named web.config and then deleting them.

  <Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
    <ItemGroup>
      <DeleteAfterTransform Include="$(OutDir)_PublishedWebsites\$(TargetName)\Web.*.config" Exclude="$(OutDir)\_PublishedWebsites\$(TargetName)\Web.config" />
    </ItemGroup>
    <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
    <Message Text="WebProjectOutputDir: $(WebProjectOutputDir)" Importance="low" />
    <Message Text="OutDir: $(OutDir)" Importance="low" />
    <Message Text="TargetName: $(TargetName)" Importance="low" />
    <Message Text="ProjectConfigTransformFileName: $(ProjectConfigTransformFileName)" Importance="low" />
    <TransformXml Source="Web.config" Transform="$(ProjectConfigTransformFileName)" Destination="$(OutDir)\_PublishedWebsites\$(TargetName)\Web.config" />
    <Message Text="Preparing to remove config transform files." />
    <Message Text="Files: @(DeleteAfterTransform)" />
    <Delete Files="@(DeleteAfterTransform)">
      <Output TaskParameter="DeletedFiles" PropertyName="deleted" />
    </Delete>
    <Message Text="Deleted Files: $(deleted)" />
  </Target>
I hope that you find this post useful.

Friday, December 9, 2011

WCF Web API security in a domain

I've been building REST services using WCF Web API for use in an intranet. Upon deployment from my desktop to a server I started experiencing the error below even though the hosting application, ASP.NET MVC 3, was successfully using Windows authentication.

System.NotSupportedException: Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.

A Google search shows that this isn't a novel situation, but I couldn't get the configuration and incantation right for Web API. Luckily, after a couple of hours of researching and fiddling with the web.config, I came across this post that revealed the solution to me.

When registering the service route:
var config = new HttpConfiguration();
   config.Security = (u, s) => {
      s.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Windows;
      s.Mode = HttpBindingSecurityMode.TransportCredentialOnly;
   };

   routes.MapServiceRoute<YourType>("YourRoutePrefix", config);

I hope that this post saves someone some time.