I have assembly A with class Z that inherits from class X in assembly B. Now in a completely different solution, I have assembly C, which uses class Z.

The compiler complains unless assembly C has a reference to both assembly A & B. Even though assembly C does not use class Z directly in anyway.

Is this expected?

It seems to me that if assembly B is missing at run time stuff blows up, but at compile time it shouldn't care.

What am I missing here?

My goal is that I can tell my clients to depend on class Z in assembly A, but I can completely reconfigure my assemblies on the other side and have no effect at all on the client when they upgrade.


 
Categories: Development

I have the following solution project structure:

  • Application.Core.Entities
  • Application.Xtend.CustomerName.Entities

In the Core project I have an entity Customer defiend. In the XTend project, I have an entity defined that subclasses Customer named xCustomer (for lack of a better name at this time...).

The idea here is that we have a Core domain model in our application. A customer can then create a new assembly that contains extensions to our core model. When the extension assembly is present a smart IRepository class will return a subclass of the core class instead.

I am attempting to map this relationship in NHibernate. Using Fluent NHibernate I was able to generate this mapping:

 

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   default-lazy="false"
                   assembly="NHibernate.Core.Entites"
                   namespace="NHibernate.Entites"
                   default-access="field.camelcase-underscore">
  <!-- Customer is located in assembly Application.Core.Entities -->
  <class name="Customer" table="Customers" 
        xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" column="Id" type="Int64">
      <generator class="native" />
    </id>
    <component name="Name" insert="true" update="true">
      <property name="LastName" column="LastName" length="255"
                type="String" not-null="true">
        <column name="LastName" />
      </property>
      <property name="FirstName" column="FirstName" length="255"
                type="String" not-null="true">
        <column name="FirstName" />
      </property>
    </component>
    <!-- xCustomer is located in assembly Application.XTend.CustomerName.Entities -->
    <joined-subclass name="xCustomer" table="xCustomer">
      <key column="CustomerId" />
      <property name="CustomerType" column="CustomerType"
                length="255" type="String" not-null="true">
        <column name="CustomerType" />
      </property>
    </joined-subclass>
  </class>
</hibernate-mapping>

But NHib throws the following error:

NHibernate.MappingException: persistent class Application.Entites.xCustomer, Application.Core.Entites not found ---> System.TypeLoadException: Could not load type 'Application.Entites.xCustomer' from assembly 'Application.Core.Entites, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'..

Which makes sense xCustomer is not defined in the Core library. I took my quandary to the NHibernate Users mailing list and StackOverflow. After some helpful suggestions and pointers, I discovered that the solution was so obvious that I am somewhat embarrassed that I couldn't see it.

The hibernate-mapping attributes assembly and namespace are convenient short cuts that allow you to not have to fully qualify your class names. This lets you have the nice mark up , but the name attribute of both class and joined-subclass elements can take a fully qualified assembly name as well.

So the above broken mapping file can be fixed like so:

 

<joined-subclass name="Application.XTend.CustomerName.Entities.xCustomer, 
                 Application.XTend.CustomerName.Entities, Version=1.0.0.0, 
                 Culture=neutral, PublicKeyToken=null" 
                 table="xCustomer">
  <key column="CustomerId" />
  <property name="CustomerType" column="CustomerType" length="255" 
            type="String" not-null="true">
    <column name="CustomerType" />
  </property>
</joined-subclass>

This works as I expected it to. So I then took a look at the Fluent-NHibernate source and created a patch complete with working unit tests to resolve the issue and submitted it to the project.

So at the end of the day, I learned something about NHibernate and the Fluent-NHibernate team got a patch to resolve and obscure bug.


 
Categories: Development | NHibernate

October 22, 2008
@ 10:12 AM

I have been getting hounded by our webmaster to supply a bio for our company bio page. Here is my first stab at it:

Bobby Johnson is a Senior Development Specialist and joined Alliance Enterprises in September 2008. Bobby is an Agile fanatic, Domain Driven Design enthusiast and Unit Testing maven who is not afraid to run with scissors. Bobby attended Southwest Missouri State University prior to bailing out to seek fame and fortune. He previously could not be contained by the Washington State Department of Labor & Industries or the Red Wind Casino.

I'll update when when the actual bio goes up.

UPDATE: Here is what actually hit the page:

Bobby Johnson is a Senior Development Specialist.  He joined Alliance Enterprises in September 2008. Bobby is involved with the implementation of the agile approach to development and also developing Unit Testing for the AWARE system.  Prior to joining Alliance, Bobby worked at the Washington State Department of Labor & Industries as a  Development Specialist.


 
Categories: Commentary | Random

Yesterday, my team had a developer forum session to assist one our own get our latest release to build on our build server from a new branch. He had been working on it for a couple days and was getting nowhere. He would follow our documented process to create the new build and when he got to the end of it the build threw the following error:

The path C:\Build\ProductReleases\FullBuildv5.4.2x\Sources is already mapped to workspace BuildServer_23.

We used the Team Explorer IDE and attempted to identify this rogue workspace. Try as we might we couldn't locate it. We tried deleting all the source code on the file system. We tried nuking all the workspaces we could see through the IDE.

In the end we had seven developers in a room shouting out ideas to a frustrated developer sitting the keyboard. So we broke for lunch.

After lunch, I returned to my desk to troll the MSDN Team Foundation Server Developer Center. Using the tf workspaces command, you can get a list of all the workspaces you have created:

C:\>tf workspaces

Server: BuildServer
Workspace Owner          Computer Comment
--------- -------------- -------- --------
BOBBY     work\Bobby 	 BOBBY

But if you add the owner switch, you can get a list of all the workspaces on the server:

C:\>tf workspaces /owner:*

Server: BuildServer
Workspace      Owner      Computer  Comment
-----------    ---------- --------- -------------------------------
BuildServer    Shane      BuildServer
BuildServer    Craig      BuildServer
BuildServer    TFSSETUP   BuildServer
BuildServer    Keith      BuildServer
BuildServer_1  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_10 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_12 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_13 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_14 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_16 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_2  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_23 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_28 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_3  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_30 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_31 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_32 TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_4  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_6  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_7  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_8  TFSSERVICE BuildServer  Workspace created by Team Build
BuildServer_9  TFSSERVICE BuildServer  Workspace created by Team Build

From this output we can see that our build service user TFSSERVICE has a lot of workspaces defined. Considering we have 3 builds so far. Something is very wrong here.

Our original error message referenced a workspace named BuildServer_23 which does show up in our list. Using the tf workspace command, we can completely remove the workspace:

C:\>tf workspace /delete /server:BuildServer BuildServer_23;TFSSERVICE
A deleted workspace cannot be recovered.
Workspace 'BuildServer_23;TFSSERVICE' on server 'BuildServer' has 0 pending change(s).
Are you sure you want to delete the workspace? (Yes/No) Y

Our build now runs as expected. It's now time to verify what all those other workspaces are and remove them if they are not needed.

Hope this helps someone out there if you are desparately googling for away around this error.


 
Categories: Development | Tools

The application I am currently working on has a hand rolled implementation of Ajax that is somewhat awkward to work with. At the end of our last sprint, I was tasked with spiking what it would take to migrate to the .NET Ajax 1.0 extensions while everyone else was working on release week tasks.

It took a couple days to figure out all the installs, web.config modifications, component vendor compatibility and other various things. But in the end, I had a simple page with two sample Ajaxified controls that worked.

I then turned to the task of unraveling the way the current implementation was wired up and modifying a single page to use the Ajax framework instead. A few minor safe refactorings and quirks later, I had a semi-functional reference implementation with one giant problem.

The page contained a series of drop down lists that filter each other as you make selections. On initial page load, I could select an item any drop down and it would appropriately modify the others. The second selection always returned the following error:

Sys.WebForms.PageRequestManagerServerErrorException: An unknown error occurred while processing the request on the server. The status code returned was: 404

Reguardless of what list I selected from first, the second request would fail. My IIS logs revealed that my request was being sent to server, but for whatever reason the URL changed.

2008-10-17 14:52:14 W3SVC1 127.0.0.1 POST /Aware/Xtend/mParticipant/NewPlannedService.aspx  80 - 127.0.0.1 200 0 0

2008-10-17 14:52:20 W3SVC1 127.0.0.1 POST /Aware/mParticipant/NewPlannedService.aspx  80 - 127.0.0.1 404 0 0

Using Fiddler, I was able to see that a value for formAction was being sent back to the client that was invalid. You can also see that the second request is going to a non-existent page:

FiddlerOutPut

I was able to resolve the issue by explicitly setting the value of my forms action back to the correct path at the end of my call back method like so:

this.Form1.Action = Request.Url.PathAndQuery

But this seemed like a hack in the worst way and smelled somewhat like moldy cheese to me. And I still didn't understand what was causing the issue.

The application makes extensive use of Server.Transfer as a "performance enhancement". I noticed that the form I was working with was one of these cases where Page1.aspx transfers execution to my Ajaxified page.

I decided to try to isolate the behavior and reproduce it in a simple example project.

I fired up Visual Studio and created a new Ajax website. I added two pages; Default.aspx and AjaxPage.aspx. I implemented a simple ajax call back on my ajax page and the default page transfer execution in its Page_Load method.

To my surprise, it worked with no problems. I didn't see the nasty error at all. I verified with Fiddler. I was stumped.

I started thinking about the behavior in my application. The only difference I could think of was that the page that was being transferred to was in a different subdirectory than the original page. So I created a folder in my test project and moved AjaxPage.aspx into it. And this time I got the error. I confirmed with Fiddler that my "Folder" sub directory was being dropped off the second request and that it was missing from the response from the first request.

My smelly cheese hack worked as well for my test project. But I didn't want to solve this issue with a server side hack. So I created the following client side Javascript to hook into the client ajax framework and solve it there in a single place:

var orginalFormAction = null;

//capture the current form action value
function BeginRequestHandler() {
  orginalFormAction = theForm.action;
}

//set the form action value back to the
//correct value
function EndRequestHandler() {
  theForm.action = orginalFormAction;
  theForm._initialAction = orginalFormAction;
}

function RegisterRequestHandlers() {

  if (typeof (Sys) != "undefined") {
  
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
    Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequestHandler);
    Sys.Application.notifyScriptLoaded();
    
  }
}

//register request handlers after the application 
//has successfully loaded.
Sys.Application.add_load(RegisterRequestHandlers);

I can then add the script to any ajax page, by adding the following code to my Page_Load event handler:

protected void Page_Load(object sender, EventArgs e)
    {
      PageScriptManager.Scripts.Add(
        new ScriptReference("~/Script/Ajax.Server.Transfer.Fixer.js")
        );
    }

Problem solved and I didn't have to rewrite the entire application to get rid of Server.Transfer calls. On to other things.

Fiddler Tip: To get Fiddler to capture traffic when you are debugging on local host, after you hit F5 to begin degugging change the address so that localhost has a "." after it. For instance, you start debugging and the you have the following URL in the Address bar: http://localhost:49573/Default.aspx Change it to http://localhost.:49573/Default.aspx hit enter and Fidder will start picking up your traffic.


 
Categories: Development | Tools

The code base I am currently working with has a collection class that inherits from ArrayList. The purpose of this class is to offer a unique list of objects and to provide case insensitive comparisons when adding a unique item to the collection. The collection does not need to be unique, but we a way to add unique things to the list is required.

My task the last week was to become familiar with the code base and identify possible refactorings. Using NDepend, I was able to determine that this class is typically used with strings. One possible refactoring I suggested was to replace this custom class with List<string>(). An out of sprint hit squad was formed to tackle doing just that. We came in on Saturday morning bright and early and got started.

Doing a global search and replace to change this custom ArrayList class with List<string> turned up thousands of compiler warnings where the method AddUnique() was called.

Our first stab at tackling this problem was to create a helper method that added an item to a given list only if that list did not already contain the item. We wrote a macro to quickly turn the old references into the new helper references. The code looked something like this:

tableList.AddUnique("item_table")

ListHelper.AddUnique(tableList, "item_table")

This seemed to get us around the uniqueness hurdle. It was a bit verbose, but it got the job done and would eventually allow us to get rid of the custom collection class altogether. We started hacking away, taking turns at the keyboard with three sets of eyes making sure we were hitting the right items and evaluating between List<string> and ArrayList where appropriate.

After a few hours of locating problem areas and fixing them with a handy macro we created out of sheer boredom, the hit squad decided this was not working. I mentioned that if we were using Visual Studio 2008, we could write an extension method that would simply attach an AddUnique() method to the List<string> class. We knew that Visual Studio 2008 allowed you to target the 2.0 framework. So we could upgrade the solution to VS2k8, leave all our projects targeting 2.0 and be able to use extension methods.

I left the 8 hour marathon triple-programming session with the goal of playing around with implementing extension methods in Visual Studio 2008. Since I was not familiar with actually writing them, I fired up my IDE and wrote a couple tests for what I wanted to happen.

        [Test]
        public void Can_Add_Unique_String_To_List_Of_String()
        {
            var list = new List<String>();

            list.AddUnique("one");
            list.AddUnique("one");

            Assert.AreEqual(1, list.Count);
        }

        [Test]
        public void Can_Add_Case_Insensitive_Unique_String_To_List_Of_String()
        {
            var list = new List<string>();

            list.AddUnique("one");
            list.AddUnique("ONE");

            Assert.AreEqual(1, list.Count);
        }

I flipped over to my Extensions library and added a ListOfStringExtensions class. To get the code to compile I quickly stubbed out the method like this:

public static void AddUnique(this List<String> list, string item)  {   }

Using the ReSharper unit test runner, I verified that my test indeed fail. The moved on to implementing the method logic. My first attempt at implementing the method looked something like this:

public static void AddUnique(this List<string> list, string item)
        {
            foreach(var s in list)
            {
                if(s == item)
                    return;
            }

            list.Add(item);
        }

This allowed my first test to pass, but not the second. So I modified the implementation like so:

public static void AddUnique(this List<string> list, string item)
        {
            foreach(var s in list)
            {
                if(String.Compare(s,item,true) > 0)
                    return;
            }

            list.Add(item);
        }

Now both tests pass. I continued down this TDD path until I had a nice set of extension methods and unit tests that satisfied all the requirements to get rid of our custom collection class. In the end I created AddUnique, AddUniqueRange, CaseInsensitiveContains, IsUnique and ToUniqueList extension methods which all work nicely together with a full suit of unit tests.

The next task at hand was to get the extension methods working in projects that were targeting the 2.0 framework. I set my unit test class to target 2.0 and verified that they still worked. I got an warning as soon as I set the framework target that I had references to projects targeting a different framework. The tests ran fine.

I then changed the target of my extension library to 2.0 and got this nasty error at compile time:

Cannot define a new extension method because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll?

Hrm.. ExtensionAttribute seems to be a 3.x feature. But I had started out this adventure reading ScottGu's blog where he says that extension methods are language syntactical sugar and should work fine with the 2.0 framework. So I fired up Chrome and hit google.

The first result for my query happened to be my good friend Nate Kohari's blog. Nate is the creator of Ninject the amazing Dependency Injection framework. He also recently release his new web site IdeaVine. He is an awesome guy  and as usual he already blazed the path I was walking down.

According to Nate, all I needed to do was add an attribute class in a specific namespace to get around the compiler issue.

 
//override the .net 3.5 compiler services for .net 2.0 compatibility
//see: http://kohari.org/2008/04/04/extension-methods-in-net-20/
namespace System.Runtime.CompilerServices  
 {  
   [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]  
   public class ExtensionAttribute : Attribute  
   {  
   }  
 } 

Everything compiles and test run fine targeting the 2.0 framework. In morning I plan to verify this by running sample code on a fresh box with only the 2.0 framework installed. As always you can get my full source code here.


 
Categories: Development | Unit Testing

August 21, 2008
@ 09:34 PM

IMG_0157

If you don't know why, you are dead to me. I couldn't get a fanboy picture of myself with John Lam, but this totally made up for it.


 
Categories: Events | Local | Random

August 19, 2008
@ 12:02 PM

I am currently attending the Devscovery conference on the Microsoft campus. So this is a perfect opportunity to meet up with my friends in the local ALT.NET group while I am here.

I turned on the batsignal and it was determined that Celtic Bayou was the location and this coming Thursday night at 5:30 is the time.

So if you are in town and have some free time, come join us and discuss all things software with fellow passionate developers. The beer is great and the food is even better. See you there.

 

What: Geek Dinner

When: Thursday, Aug 21st 2008 5:30 PM - Till we all leave

Where: Celtic Bayou


 
Categories: Events | Local