Archive for the ‘C#’ Category

VB.NET ‘Type or Namespace cannot be found.’ after converting VS 2005 projects into VS 2008

October 23, 2009

I am converting some VB.NET projects from VS 2005 into VS 2008. I had converted the projects ‘Animals’ and ‘Food’, put them into a Solution, Zoo.sln, added a Project Reference for Food into the Animals project and compiled the Solution which duly compiled and ran.

Visual Studio 2008 Conversion Report Ambiguous
But, examining the Conversion Report for ‘Food’, I noticed that only the Food.vbproj file was marked as converted. The summary at the end of the log said:

Converted: 1 file.
Not Converted: 72 files.

This made me worried. Why were there 72 files Not Converted ? Had I actually converted Food properly ? Angst got the better of me, so I Unloaded and Removed Food from Zoo.sln, retrieved the source again from Visual Source Safe and reconverted the Project.

I got the same result: 1 file converted (just the vbproj) and 72 files with no status next to them (but no errors either) and a count of 72 ‘Not Converted’.

I Googled here and there and eventually found a forum post by the knowledgable Peter Bromberg which said that Class files (.vb and .cs) will not by touched by the VS 2005 to VS 2008 Conversion. That put me at ease. So then I re-added Food to Zoo.sln, added the Project Reference into Animals as before and recompiled.

This time 102 errors: Horrific memories of school examinations covered in red pen filled my mind.

All the errors said the same thing: ‘Type or Namespace xyz cannot be found. (Are you missing an Imports or Assembly Reference) ?‘ All the errors were in ‘Anmals’ referring to unknown types which I knew existed in ‘Food’.

Well, I checked the Project Properties for ‘Animals’ and the Reference to Food ws there and it was to the correct Food.dll. I removed the reference, recompiled Food and re-added the Reference. Still 102 errors. Things hadn’t looked this grim since the days I flunked MacroEconomics 2A with a score so low it had to be examined through a microscope.

Prodding The Corpse

Here was a typical line returning two unknown type errors on MonkeyDrink:
Dim fermentedCoconut As MonkeyDrink = New MonkeyDrink()

As an experiment I tried the following:
Dim fermentedCoconut As Food.MonkeyDrink = New Food.MonkeyDrink()

To my amazement, Food.MonkeyDrink appeared in Intellisense and resolved to a known type, reducing my error count. So Animals obviously had a valid Reference to Food. Why then the compile error ?

Now you’re probably thinking ‘the dolt has left out his Import statements in the class files’ but remember these projects were converted – they never had Imports statements in them in the first place, yet Animals had always compiled with Food before. WHY was it chucking a spaz now ? The pain, the pain, the journey of pain…

Unknown Feature #999

Checking again the References Tab in the Property Page for the Animals Project, I clicked on Food in the References list then scrolled further down and noticed for the first time a pick list of namespaces from all the Referenced projects: Lo and Behold, Food was not selected. Once I selected Food (thus telling the compiler to Import all the Namespaces from Food) and recompiled, my errors vanished with the silken ease of Master Ninjas after a successful assassination.

The miraculous feature I had discovered is the Visual Studio Imported Namespaces List which MSDN beautifully describes here

The Imported Namespaces List is only available in VB Projects (not C#), that’s why I had never seen it before.

So Now I Know

If your Types cannot be found in your VB.NET project but you know the containing project is referenced, or maybe you’re wondering why your Class files have absolutely NO Imports statements in them, have a look at the Imported Namespaces List in the Project Designer via Project Properties. It’s….how you say…verrrrry nice.

Advertisements

Regex For Alphanumeric Plus Punctuation

November 6, 2008

My knowledge of Regular Expressions is marginally below that of a lobotomised axolotl, but I know that Regexes are powerful and good, sort of like King Arthur of the Britons prior to the Lancelot betrayal or a Bex, though perhaps not quite as addictive. So today I made one.

Project Numbers in our Universe here at anonymous megacorp international are no more than 12 characters long, are alphanumeric but may also contain hyphen, fullstop and colon. It took me a few Googles to hit on a good introductory Regex web-page, that helped me solve the problem, so maybe while this issue didn’t quite match my full criteria for a Journey In Pain, it did go close. So here it is:

Regex projectNumberRegex = new Regex("^[-a-zA-Z0-9:.]{1,12}$");
if (!projectNumberRegex.IsMatch(dto.ProjectNumber))
{
...run away screaming
}

Here’s Why It Works

a-zA-z0-9 are the alphanumerics
:. are colon and full-stop (not the Braille symbol for ‘No Smoking’)

– (hyphen) is placed at the start of the string because if I place it between ‘9’ and ‘:’, say, the Regex Parser will interperet as a range, which can cause it to fail if ASCII(9) is greater than ASCII(-), or sneakily introduce a FALSE SUCCESSFUL range condition where none is intended.

Hyphens cannot be escaped by backslash, hence must appear either first or last in your Regex to avoid being interpereted as a range comparison. I put it at the front of the allowable characters based on the advice on this page.

[] is for grouping. It means “any of”.

^ (caret) is the ‘start of line’ character. I’m telling the Regex parser that the first character in the input string must be whatever follows the caret, which is anything in the [] grouping.

$ means “end of pattern”. This means that ONLY the sequence prior to the $ are legal. If there are additional characters in the input then the Regex fails. This is what I want. I don’t want ProjectNumber to contain anything else except the stuff in the [] group.

{1,12}means the grouping must appear between one and 12 times. That means empty string will not succeed, neither will a string of 13 or more chars.

Glorious.

In your GILLS, Ambystoma Mexicanum

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.

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