Saturday, August 30, 2008

Cannot debug web based apps in Visual Studio (VS2008)

The company or product being named and shamed: Eset NOD32 AntiVirus.

Here's why: I was trying to debug a Silverlight application i had just whipped up, but i had an issue - i would press F5 in Visual Studio, IE (IE7 to be exact) would pop up, but i would just get a "Internet Explorer cannot display the webpage" message in IE, along with the usual list of suggestions to fix the problem. Upon checking the url in the address bar, i see it is pointing to the correct place:


so of course i initially think the problem was my fault and spend some time checking the code for errors, but of course there were none. So i loaded up a current web application that i am working on, hit F5, and the same thing happens. It has been about three weeks since i worked on that web application, and the only changes that have been made to this machine in that time are when i installed NOD32 and SP1 for Vista. As i had installed SP1 just a day ago, and because it is a major install (i.e. heaps of critical OS files get updated), i thought that it must have caused the issue. So i did what any self respecting geek does - i asked Google. It's not easy formulating a search query when you don't know exactly what the problem is, so i started with:

vista sp1 cannot debug web application

and after checking a few likely hits on the list i start noticing a recurring theme: Eset NOD32 was being blamed for the behaviour. The problem occurs because NOD32 adds an entry to your hosts file:

it's the entry at the bottom, the one that says "::1 localhost". I'm not sure exactly *why* it adds the entry, but obviously it's there to foil those badass pieces of malware that people get when they visit dodgy porn sites. But it also has the side effect of breaking the mapping between the loopback and the name "localhost", so when Cassini spins up and tries to serve my web or silverlight application it cannot resolve "localhost" back to the local machine.

Fixing this is easy - just remove the entry from the hosts file. And i have to say shame on you Eset, for not considering this behaviour, and for not checking for the presence of development tools in your install process.

To remove the entry:
- find your hosts file. This resides in %windows%\system32\drivers\etc, it is just called "hosts", with no suffix. This location is hidden, so you will have to make sure that both hidden and system files are visible.
- if you are running XP, you can just load the file into Notepad, remove the line, save it, then rerun your VS project.
- if you are running Vista, you have to jump through a few more hoops first. You need to take ownership of the file, to do this start a command prompt with administrative privileges:

either type Start-R, type cmd and then press Ctrl-Shift-Enter, and accept the UAC prompt
- or -
Start->All Programs->Accessories, right click on Command Prompt, choose Run As Administrator, and accept the UAC prompt

Then type the following commands:

take ownership of the file (so that you can change the ACLs on it)

c:\>takeown /f c:\windows\system32\drivers\etc\hosts

then you need to grant yourself full access rights to the file:

c:\>icacls c:\windows\system32\drivers\etc\hosts /grant [YourUserName]:f

then you can just load it into Notepad, remove the line, and save it. Of course it also wouldn't be a bad idea to revoke your access rights to the file once you have edited it, just to make sure it doesn't "accidentally" get modified without you realising it (modifying this file is an easy attack vector for malware). This is what the process looks like:

Those whited-out bits are just my username, you don't need to know what that is :) Interestingly enough, when i edit this file and save it, Windows Defender captures the change and prompts me to accept or revoke the change, but this never happened when i installed NOD32. I can't believe that Defender gets suspended while an application is installed (otherwise it would never detect that some malware just installed itself), so maybe NOD32 is doing something special during its install process.

Here are a couple of references that were helpful in diagnosing this problem:

Keywords: VS2008, Eset, Nod32, debugging, F5

Thursday, August 14, 2008

Using Trim() in SSRS2005 - and how it doesn't work

I found a situation today where the Trim() function doesn't work when used in a textbox expression.

I had a cell in a table that was showing the notes associated with a record, so the expression was simply:

= Fields!Notes.Value

While viewing the generated report, it was noticed that some notes had a lot of whitespace either at the leading or trailing end of the note, which caused the whole row in the table to expand in size as the note text wrapped, so I ended up with an effect like this:

This can look pretty ugly on a report. So the simple solution would be to trim the whitespace from the note text as part of the textbox expression:

= Trim(Fields!Notes.Value)

Bzzzzzzzztttttt!!!!!! Wrong answer - it didn't trim the note text at all. OK, time for Plan B, do a specific trim:


But once again, no cigar (and yes, i know that Trim() should just call LTrim() and RTrim() under the hood, but i would be a bad developer if i just went with that assumption and didn't try this option). I'm thinking that this was caused by a failure to implicitly cast the Field!Notes.Value from an object to a string, so the various trim functions failed. So i though of another approach:


and success!!!!!!...... and failure. This expression worked perfectly on rows that had a valid note, but on the ones where the value was null i got the familiar #Error statement in the textbox instead of a blank value:

This meant one more modification was required - i needed to check for a null value before i attempt the ToString().Trim() on the value. I am not a fan of the VB style IIf statement, as it doesn't shortcut (this means every argument in the function gets evaluated, regardless of the result of the expression), this means that the expression:

=IIf(IsNothing(Fields!Notes.Value), Nothing, Fields!Notes.Value.ToString().Trim())

would still error because the false part of the IIf would still get evaluated every time. The easy way round this is to just use a bit of custom code, and this is what i ended up with:

Textbox expression:


and the custom code:

Public Function TrimStringValue(ByVal fieldValue As Object) As Object
    If IsNothing(fieldValue)
        TrimStringValue = Nothing
        TrimStringValue = fieldValue.ToString().Trim()
    End If
End Function

Keywords: ssrs2005, ssrs, trim, ltrim, rtrim, iif