Archive for May, 2008

Cannot Load File Or Assembly After Renaming DLL

May 22, 2008

Solution

Use an Elephant gun.

Details

DDK renamed one of our DLLs from AgentMaintenance.dll to CompanyMaintenance.dll. After my next ‘Get Latest’ from our source code repository the solution failed to build saying ‘Could not load file or assembly AgentMaintenance’. No-one else in the project team was getting this error. It was obviously a conspiracy.

I did the following:

  • Searched through all References in my Visual Studio Projects looking for AgentMaintenance
  • Deleted everything in Temporary ASP.NET Files folder
  • Deleted all obj and bin files from my main project
  • Courtesy of Eric Falston, I stopped the World Wide Web Publishing Service, closed Visual Studio then re-opened Visual Studio and re-started the Service (this worked once).
  • Commenced video and phone surveillance of my workmates.

None of this solved the Assembly loading issue but the dossier on my Brazilian workmate proved to have significant omissions.

Returning to the issue at hand, DDK suggested using ‘Find In Files’ in Notepad++ to look for occurences of AssetMaintenance and I found a few in intruiging locations such as a Subversion .tmp file, the Visual Studio .suo file and a redundant project, AgentMaintenance.Persistence, which was no longer part of our VS solution.

I deleted the SVN .tmp file and the .suo file and the solution successfully built (once). Thereafter I found that deleting the .suo file after every build would allow the solution to load and run succesfully without compaining that it could not load AgentMaintenance.dll.

This kept me happy for a while as I reasoned I could find the real problem at a later time instead of just dealing with the problem symptomatically by deleting the suo file prior to each build. But then IT DIDN”T WORK. Not even deleting the .suo file could prevent the Godzilla-like re-emergence of “Cannot Load file or assembly…”

So, finally, and not before time, I pulled out the Elephant gun.

KER-BLAM! I exterminated my SVN Working Copy, did a clean SVN Checkout and re-built successfully. 1,000 builds later Godzilla still sleeps.

If the above doesn’t help, try this very informative thread.

PS
For astounding video footage of what is possible with half a lobster, twelve cubic yards of Helio brand ball-bearings and a rubber mallet, please contact Blog Author and quote BRAZIL-808-MA.
Caution: Some scenes may disturb younger viewers

Subversion: “Edit Conflicts” Unavailable

May 14, 2008

We are using SVN externs to selectively pull in revisions from a “Framework” Project which functions as a code library for our app. Our SVN process is to create a Working Copy from a DEV folder in the repository, commit to DEV, and then subsequently svnmerge (via a script) from DEV to a TRUNK folder which forms the basis for our deployments.

Pre-Revolutionary Conditions

I put some code into the Framework library and therefore updated the svn externs for the Framework folder in our app. I then did a SVN Commit to DEV and was subsequently ambushed by a SVN Conflict on the Framework folder when executing our merge-from-dev script when preparing TRUNK for a deployment.

SVN Goes Stalinist

In order to view the conflict in Tortoise SVN, I created a SVN branch from TRUNK itself, but Tortoise SVN did not have any option for “Edit Conflicts”, “Resolve using mine” or “Resolve using theirs” under the “Check For Modifications” Context menu or anywhere else. In a cruel parody of Stalinist democracy, all it had was the “Resolved” option. There were no .mine or .rnnn files for the folder. In addition, the Folder still had the old externs in place in its SVN Properties. How to resolve the conflict AND get the CORRECT svn extern settings into the Folder properties ?

Solidarity in the Dialectical Struggle

Our site SVN expert showed me the ACTUAL file which was in conflict which was the read-only hidden _svn folder which belonged to the Framework directory. He did this by simply enabling Hidden Files in the Folder View options. That revealed this sucker:

Subversion Properties Hidden Folder

But even THIS file does not have .mine and .rnnn files generated for it; you still can’t do an “Edit Conflicts” on it because it’s read-only. So now we could see what was in conflict but couldn’t do any edits on the Conflicts.

What you CAN do, however, is a “Compare to Base”. This allows you to see what text in the svn Properties file has caused the conflict, which of course was our updated externs.

Workers’ Paradise

Using the principles of Russian Roulette-Driven Development I suggested we update the externs to the correct values in the TRUNK working copy then accept the only option Tortoise cared to present to us – namely “Resolved” – then blast away with a Commit to TRUNK…and it worked…

(but we did check the extern properties after clicking “Resolved” and before hitting “SVN Commit” – there are limits even to Russian Roulette).

Addendum 16-Apr-2009 : .suo File Conflicted

I noticed a few people accessing this post using the Google search terms ‘svn .suo file conflicted’. Fixing this one is easy – delete the .suo file from Subversion. If you really need to fix the conflict, do it any way you can ‘Resolve using theirs’ or ‘Resolve using mine’ are equally acceptable.

The .suo file should not be added to source control because it contains user-specific Visual Studio settings such as locations of your breakponts, the user’s VS window layout (e.g. do they have ‘Server Explorer’ window open and if so where do they want it located on the screen) etc. SUO stands for ‘Soluton User Options’.

Liberation From Wage Slavery

Personal settings in the VS IDE are irrelevant to the actual code in the solution and hence should not be stored in source control. All you will achieve is a meaningless SVN conflict because User TREV likes Server Explorer open in Visual Studio whereas user BRIAN does not. That’s why the conflict can be resolved in any way you like.

Be free, comrade! Kill from SVN disgusting suo file!

Here’s the MSDN spiel on what the .suo contains.

Unused usings

May 12, 2008

Having Obsessive-Compulsive tendencies, I spent some time stripping unused Usings from our .cs files, all 626 of them. Smug with my efforts, I then wondered if it had achieved anything useful, specifically if it had reduced the size of our generated dlls. I was a little dissapointed to discover that it had not but OTOH it seems that I probably improved the compile time of the app a little bit.

This post by Andrew Troelsen of the MSDN C# Team says that the C# compiler, csc.exe, ignores Usings and Assembly References not referenced in code, while under the Comments in the same post Anthony Ashe points out that the compiler still does a ‘copy local’ for unused assemblies leading to redundant crud lying around in your bin directories as well as your source code.

In addition to the above, as Patricia Shanahan points out, it is good practice to remove Unused Usings as inspection of your Usings helps to convey to maintainers of your code what your code is likely to do and affect.

Now, if you’ll excuse me, its time to Dettol the cat.

LINQ context.SubmitChanges() does not add record to database

May 8, 2008

This never happens.

If you think that context.InsertOnSubmit(entity) is not adding the entity to your Context then you are doing something wrong.

In my case, I had code like this:


ProductContext context = new ProductContext();
Product product = new Product();
product.Id = productId;
product.Name = productName;
product.Description = productDescription;

context.InsertOnSubmit(product);
context.SubmitChanges();

Totally straightforward, but when I checked the database, the Product table did not contain the new Product record I had created above. But this problem only occurred on our Integration Test server, not on our Dev box (Why?). So began my journey of pain….

I ran the program a few times and noticed that my EntitySet, context.Products, was increasing in number each time I passed through the AddProduct method snippet above, but the database table, Product, as viewed through VS Server Explorer did not have the same number of records as the context. WHY?!!! (Some of you have guessed already.)

I started Googling for help: “InsertOnSubmit fails”; “SubmitChanges does not save”; “LINQ insanity coronary apoplexy” etc. Then spake Thrifty Dave, our noble Team Leader: “Perhaps the Connection Strings are different on the Test box,” suggested Dave between mouthfuls of remaindered Sushi. My pangs of internal anguish commenced immediately. This had the ring of truth as well as the scent of slightly fermented Wasabi paste.

I checked the Connection Strings: yep, the Context on Integration Test was pointing to “ProductTest” database whereas the actual database I was looking at was “ProductLive”. Too simple. There was NO problem with context.SubmitChanges(). I was just looking at the wrong database. *blush* (Respectfully please now imagine a luminous red object larger than the Hindenburg and covered in Wasabi paste).

Moral Of The Story

context.SubmitChanges() always works. If you think its not working, then its your fault. Look elsewehere. Maybe check your ConnectionStrings.

Plausible Deniability

The reported bug was in a Windows Service which utilizes the same database as the main application. On the IntegrationTest server, the Windows Service app.config had its ConnectionString set to “ProductLive” database due to an error in our deployment scripts. My colleague, who wrote the Windows Service told me that data was not being found by the Windows Service and HE was checking “ProductLive”, based on the (faulty) Windows Service app.config.

So I believed what I was told.
But, yes, I should have checked, and I should have realised quicker what was going on

Life Force Depletion: Classified.

SiteMap External Link “not a valid virtual path”

May 2, 2008

So, I was asked to add a link to an external Web Site from the Main Menu of our app and to display it in a new browser window.

The Main Menu is composed of SiteMapNodeInfo nodes that are consumed by a custom SiteMapProvider derived from StaticSiteMapProvider and eventually fed to a TreeView for rendering.

Using the principles of Orangutan-Driven Development I sledgehammered the code with a blunt instrument to see what would fall out the tree. Thus:


SiteMapNodeInfo cityScopeNode = new SiteMapNodeInfo("Links", "http://CityScope.com", "Links");
siteMapBuilderService.AddNode(cityScopeLinkNode, Globals.RuleNames.ExternalLinks, 3);

..and was duly greeted with the System.Web.HttpException and message “http://CityScope.com not a valid virtual path” (no bananas).

The bulk of my problem was solved by Joe Audette who showed me that the URL in the SiteMapInfo node must be a path that resides within the application, the validation for this being the .NET Framework call:


System.Web.StaticSiteMapProvider.AddNode(SiteMapNode node, SiteMapNode parentNode)

Deep within my Reptilian Brain Stem, inchoate impulses began to coagulate: SiteMap…Site…yeeessss…in-TER-naaaaaallll. Fair enough, since its a SiteMap then external Links are probably contra-indicated, but it IS nevetheless possible to include an external link when using a SiteMapProvider, by kind of sneaking around it.

Joe pretty much gave me the solution by referring to the MenuItemDataBound event of his Menu Control and explaining that “AFTER the SiteMapNode is in the nodes collection you can get away with changing the Url to an external link.”

I didn’t have a Menu control, but I did have a TreeView – ergo:

Step 1: Initialize SiteMapNode to something that passes the AddNode validation – an empty string will do.

Step 2: Handle the TreeView’s TreeNodeDataBound event to set the Node’s URL to an external link.

Step 3: Set the SiteMapNode’s ‘Target’ property to “_blank” if you want the external Link displayed in a new browser window.

From our Web Client Software Factory ModuleInitializer :


protected virtual void RegisterSiteMapInformation(ISiteMapBuilderService siteMapBuilderService)
{
SiteMapNodeInfo LinksRootNode =
new SiteMapNodeInfo(LinkNames.Links.Name, LinkNames.Links.URL, LinkNames.Links.Name, "");
// Put string.Empty in place of external Link to avoid HttpException SiteMapNodeInfo CityScopeNode =
new SiteMapNodeInfo(LinkNames.CityScope.Name, string.Empty, LinkNames.CityScope.Name);
siteMapBuilderService.AddNode(LinksRootNode, 4);
siteMapBuilderService.AddNode(CityScopeNode, LinksRootNode);
}

In our MasterPage where the TreeView is rendered:

// HandleTreeNodeDataBound
protected void TreeView_TreeNodeDataBound(object sender, TreeNodeEventArgs e)
{
// Initialise the CityScope Link (which is external)
// and display it in a new browser window when selected

if (e.Node.Text == LinkNames.CityScope.Name)
{
e.Node.NavigateUrl = "http://CityScope.com.au";
e.Node.Target = "_blank";
}
}

Life Energy Consumed: 41 mins.

Acknowledgments

Thanks to Scott Berkun for the inspiration for ODD