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