.Net ramblings
# Thursday, 10 August 2006
Crystal Reports: join / concatenate null strings
I was getting blank fields in my crystal report if one of the values in the formula was null.
Thanks to this post i know better than to trust Crystal's crummy concatenation rules.  Here is what Gundula Wangerin had to say:
A string concatenated with null always gives null.
You have to check if the first name is null with
     if not IsNull(firstname) then 
        lastname + " " + firstname

Thursday, 10 August 2006 17:31:20 (GMT Daylight Time, UTC+01:00)  #    Comments [3]  .Net General | .Net Windows Forms | Asp.Net

# Friday, 04 August 2006
Crystal Reports: Suppress doesn't work for Count(x) = 0
I picked up a tip on the Internet to display a "No records" message if the report contains no records, rather than leaving the user with an empty screen.  Simply Format the text field and enter a formula next to 'Suppress' with something like
Count({Table.Field}) > 0
This will suppress (hide) the message if there are records in the report.

I tried using a similar approach to hide a text field when there are no records, so it is essentially the same thing in reverse.  You would think a simple formula on the 'suppress' property this would achieve the desired effect:
Count({Table.Field}) = 0

But apparently the value returned by Count can be null if there are no records.  so you have to use:

IsNull(Count({Table.Field})) OR Count({Table.Field}) = 0

This is just another crystal reports annoyance, of which there are many.

Friday, 04 August 2006 11:26:38 (GMT Daylight Time, UTC+01:00)  #    Comments [9]  .Net General | Asp.Net | Windows Server

# Wednesday, 02 August 2006
Crystal Reports: not picking up correct date format
i'm part of the dd/MM/yyyy world, and that often means running into problems when using software developed with MM/dd/yyyy defaults, such as crystal reports. 
i have all the report options set to use the system defaults, which are regionally set to ireland in windows, but that isn't enough, the dates still come out in MM/dd/yyyy format.  i have the date + date/time fields customised within crystal reports to dd/MM/yyyy but that isn't enough either.  with lots of hours googling and no answers that worked, i resorted to searching the registry and found that some of the user accounts were still using US regional settings.  If you look in HKEY_USERS > you see a list of all the account IDs on the computer.  My guess is that crystal reports must use the SYSTEM account or another non-interactive account, and it takes the regional settings from there.  So if you search for sShortDate in the registry, you will find all the appropriate settings and can replace the MM/dd/yyyy values with your preferred format.
i had to reboot to get it to take effect. 

Wednesday, 02 August 2006 20:45:07 (GMT Daylight Time, UTC+01:00)  #    Comments [12]  .Net General | Asp.Net | Windows Server

# Thursday, 27 July 2006
Crystal Reports: problems changing database connection at run time
i ran into a problem with my Crystal Reports.  instead of using the usual Typed Dataset approach, where you use Report.SetDataSource(DataSet), i decided that was too much hastle and it seems faster and simpler just to design the query in the Crystal Reports 'wizard', and then supply parameters and set the record filter appropriately.  what i didn't know was that it was insanely complicated to direct the report to a different database path at runtime (such as most users would have in their deployment environment, whether for Access or SQL server). 

i was using Report.SetDataBaseLogon("admin", "") etc and all sorts of variations but none of them were working.  I kept getting Logon Failed exceptions.  Apparently you need to iterate through each table used in the report and set the source database for each one.  Not only that, but neither of the following lines of code has any effect:
Report.Database.Tables[i].SetDataSource("admin", "", DbPath, "")
Report.Database.Tables[i].LogOnInfo.ConnectionInfo.ServerName = DbPath
apparently you have to create a TableLogOnInfo object and use ApplyLogOnInfo() with that on each table. 
here is what does work:
TableLogOnInfo t = new TableLogOnInfo();
t.ConnectionInfo.ServerName = dbPath;            
for(int i=0; i<rpt.Database.Tables.Count; i++)

Thursday, 27 July 2006 16:31:47 (GMT Daylight Time, UTC+01:00)  #    Comments [3]  Asp.Net

# Tuesday, 25 July 2006
Network cable unplugged in XP, after installing Vista
i installed vista on a second partition and when i went back to XP, the LAN reported a network cable unplugged.  of course it wasn't, and apparently the IPv6 protocols used in Vista caused some confusion between the router and network card.  turning off the computer and router for a minute or two seems to do the trick!

this useful post explains it better

Tuesday, 25 July 2006 11:05:25 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  

# Monday, 24 April 2006
HowTo: cancel an onbeforeunload event
if you're like me and use the onbeforeunload event in a web page to display a reminder to a user who might unintentially lose work by browsing away from the page, then you might be trying to find a way to cancel the event in the case where the user clicks the save button (they obviously don't need reminding now that they have clicked the button...)

on the internet you will find many people suggesting you use something like
window.onbeforeunload = null
but this does not work for me in IE6.  reading up in the MSDN docs for the event object i found a reference to the event.cancelBubble property, which i thought was the solution. but thanks to Orso who pointed out that setting "event.cancelBubble=true" is useless, the way to get rid of the confirm prompt is to exclude the return statement altogether, i chose to use a boolean variable as a flag to decide whether to return something or not. in the example below i add the javascript code programattically in the code behind:

	Page.ClientScript.RegisterStartupScript(typeof(String), "ConfirmClose", @"
window.onbeforeunload = confirmExit;
function confirmExit()
if(postback == false)
return ""Please don't leave this page without clicking the 'Save Changes' or 'Discard Changes' buttons."";

then my save button contains the following aspx markup:
    OnClientClick="postback=true;return true;"
this sets the 'postback' variable to true, which gets picked up in the confirmExit() function, having the effect of cancelling the event. 

hope you find this useful.  it is tested and works in IE6 and FF

Monday, 24 April 2006 17:10:13 (GMT Daylight Time, UTC+01:00)  #    Comments [16]  Asp.Net

# Wednesday, 12 April 2006
FindControl() won't find the control....
my aspx page uses a master page, so all the content is inside a ContentPlaceHolder. 
aparently Page.FindControl() only works within a single container, which is really poor functionality if you ask me. 
to complicate the situation further, my aspx page has dynamic controls inside a Panel. 
in order to access the controls of my user control, from the code-behind of the page, i first had to find the panel and then the user control, and then i could finally use that to find the controls i wanted. 
note: you don't have to use the client ID of the control ...ctrl00_blah_blah_blah_YourControlName... when you use the above method, you just use the name of the control, e.g. txtFirstName. 

Wednesday, 12 April 2006 15:27:51 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  Asp.Net

# Sunday, 05 March 2006
The Microsoft Origami Project and back to hand-writing
Screenshot of origami hand-held (probably)For anyone who hasn't heard the buzz about Microsoft's Origami Project, take a look at this vido file to get a glimpse of what it is probably about.  the video is a year old but i reckon it's a fairly accurate preview of the real thing.  the thing that really struck me about the video was that people were writing hand-written notes to each other, in emails, messages etc.  What a bizarre idea.  Yeah we've had PDA's without keyboards for a long time, but they only ever had a very small user base, because of the need to learn a new form of writing that the palmtop could understand. traditional touch screen hand-writing technology is woefully slow to right messages of any length on.   if the Origami device becomes mainstream, which i think it probably will, then it is quite a departure from the way we interact with computers since they were invented. 

personally i do so much typing and so little hand-writing that i tend to think about pen + paper as an old thing i left behind many years ago.  But... when you stop to think about it, emails and 'typed' communications lose a huge amount of personality compared with traditional hand-writing.  You can't identify the writer of an email based on the style of writing, like you can with a hand-written letter from someone you know well.  emails are usually so limited in expression that we have created a whole new culture of emoticons to bridge the gap, but it's hard not to come across as cheesy and immature when you write things like :-)  :O)   :^) etc...

Screenshot of origami hand-held (probably)We've all got very good at typing, because computers understand fixed characters much better than squiggles of writing.  Typed content is also more efficient in terms of storage size, and search capabilitiy.  You still can't meaningfully scan a JPEG of a hand-written letter and be sure to get all the words out of it.  But it looks like that is the way Microsoft are headed.  It is really a massive shift if this takes off, because the modern computer experience is built around typed content.  The internet would be nothing if we had to wade through volumes of illedgible hand writing before we found the information we wanted.  Obviously this is looking at the extremes, and we'll always have typed content with us, but to me it seems like this is the first mainstream introduction of mixed text content arriving on our desktops, from the pen and the keyboard. 

In the grand scheme of things, i actually think typed content will be a blip on the radar of the way we record text information.  For thousands of years we've been writing things down, and i can't think of any good idea for why that should all be thrown out the window, except technology limitations.  It looks like Microsoft are challenging those limitations.

Sunday, 05 March 2006 12:44:07 (GMT Standard Time, UTC+00:00)  #    Comments [0]  General

# Friday, 03 March 2006
Compiling Asp.Net 2.0 to a single assembly
I wanted to install my web application assembly into the GAC, but this is made more complicated by the multitude of assemblies produced by VS when i publish the web site.  On the newsgroups, i found some talk of a tool called Merge_Aspnet.exe but i couldn't find it anywhere.  Eventually i found it as a download on MSDN, it is bundled as part of the Web Deployment Projects.  You install it, and then right-click your project in VS and you should see a new menu item "Add Web Deployment Project".  I am baffled as to why they didn't just add a new project type in the list of projects under "Deployment".  There is a link to "Search online templates" so i think it should really be available there.  but it looks like MS did a hack just to add in a new item to the project context menu.  but it works... so i'll stop complaining. 

Friday, 03 March 2006 15:43:20 (GMT Standard Time, UTC+00:00)  #    Comments [0]  .Net General | Asp.Net

# Saturday, 18 February 2006
HowTo: Get Write Access to an ApplicationData folder in ASP.NET
In a web application i'm working on, i needed to get write access to a folder, and preferably not the temp folder because the data should be kept reasonably safe from being deleted accidentally.  If it was a windows-forms application this would be easy, i would just use Application.UserAppDataPath.  So i thought for asp.net, i could use Environment.SpecialFolder.ApplicationData but this maps to the folder for the current user logged on to Windows, not the process running the web site, or the authenticated web site user.  So i just skip up 2 parent directories from that, and use the current Principal.WindowsIdentity to find the actual process running ASP.NET, and then deduce the correct folder, which by default will have write permissions for Asp.Net.

Here is the code:
string Username = Path.GetFileName(System.Security.Principal.WindowsIdentity.GetCurrent().Name).Replace(" ", "");
string UserAppFolder = String.Format(@"{0}\{1}\Application Data", Directory.GetParent(Directory.GetParent(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)).FullName).FullName, Username);

By the way, the use of Path.GetFileName is entirely intentional, it solves the case where the current user is "NT Authority\Network Service" by yielding "Network Service", which is what we are interested in.  

This will hopefully come in handy for my 'zero configuration' idea for the application.  Next time you need a write folder, it may be a good idea to use this instead of making users specify write permissions for a custom folder. 

Saturday, 18 February 2006 19:11:26 (GMT Standard Time, UTC+00:00)  #    Comments [2]  Asp.Net