John's profileJohn BarshingerPhotosBlogLists Tools Help

Blog


    October 09

    ASP.NET UrlEncode? not so fast, grasshopper.

     
    One would think using Server.UrlEncode() AKA HttpUtility.UrlEncode would take care of all the special characters in whatever string you pass it and return to you a URL that you can actually use. After all, that's what the name of the method implies, doesn't it?
     
    Au contraire! a bad thing that UrlEncode does is replace spaces with "+". You would think this is ok and sometimes it is but sometimes it is not. The better thing to do is replace spaces with "%20". Luckily, there is a new method which does just that. If you are having problems feeding out URLs that work, try this method instead:
     
    System.Uri.EscapeUriString()
     
    --------
     
    Qapla'
    August 18

    Intel X25-M SSD RAID 0 Performance/How to zero out/reset to factory performance?

    This past weekend I bought a second 80GB X25-M from NewEgg.com because they were on sale for a good price. (note: I’m talking about Gen 1 X25-M’s in this article). I liked having an SSD running under Windows 7 for my software dev box so much that I decided it can only get better if I get another and stripe two of them in a RAID-0 set. I assumed this would help me in two ways: first this would give me approximately 150GB of disk space instead of 75GB; and second, I expected read and write performance to scale to almost double what I get in a single drive. Now read performance is excellent on a single drive, Intel claims up to 250MB/s. However, write performance, although good, could be better. Intel claims write performance of up to 70MB/s. So, I was expecting to throw these 2 SSDs in a RAID-0 set served up by the Intel ICH10R on my ASUS P5Q-E motherboard and get around 400MB/s read and 140MB/s writes. Here’s what I actually found:

    test MIN MAX AVG Acc Time Burst CPU
    SSD1-R 178.6 221.3 209.1 .1 98.8 2.8
    SSD2-R 110.9 221.7 200.6 .1 101.5 2.7
    SSD1-W .1 78.4 66.8 .1 98.9 1.8
    SSD2-W 36.9 77.8 71.6 .1 101.2 1
    STRIPE-R 145.3 336.7 258.2 .1 146.9 6.6
    summed-R 289.5 443.0 409.7 .1 200.3 5.5
    STRIPE-W .2 135.8 87.1 .1 95.4 2.2
    summed-W 37.0 156.2 138.4 .1 200.4 2.8
    STRIPE-W+ .7 152.5 116.9 .1 837.7 3.9

     

    SSD1-R is the read results from HDTune for reading on my first Intel X25-M. SSD2-R is the read results from HDTune for my second Intel X25-M (both are using AHCI and treated as single drives in the BIOS). Similarly, SSD1-W and SSD2-W are the HDTune results for writing.

    summed-R and summed-W are simply the sum of the results I got from both drives in individual Read and Write tests. These are the numbers that ideally I would like to see in the striped set.

    STRIPE-R shows the actual numbers I got for reading the striped set of SSDs. STRIPE-W shows the actual numbers I got for writing the striped set of SSDs. STRIPE-W+ is the same as STRIPE-W except that I turned on write-caching for the RAID volume via Intel Matrix Storage Manager.

    As you can see, the striped set got me nowhere near my expectations, every metric for STRIPE-R and STRIPE-W was much less than ideal amounts calculated by summing the individual drives metrics.

    One thing that really bugged me was the very low MIN write times for the individual SSD test. Take a look at these pictures and you can see ridiculous spikes in the performance graphs from HDTune.

    SSD1-W-BEFORE

    SSD1-W (above)

    SSD2-W-BEFORE

    SSD2-W (above)

    Those are not what I call pretty graphs. The thing to remember with SSDs (in layman terms), is that once every page on the disk has been written to, in order to write to that page again, the SSD must first erase (clear out all the electrons) in every bit on the page prior to writing the actual data. This could explain what we’re seeing above.

    Now what about reading? Let’s take a look at those graphs:

    SSD1-R-BEFORE

    SSD1-R (above)

    SSD2-R-BEFORE

    SSD2-R (above)

    The read graphs above are not too bad but still not very smooth. I have no explanation for this result…

    Well, the next thing I decided to do was try to figure out how to restore these SSD’s to factory performance by clearing all the pages on each SSD. After searching for some time, I found this page: http://www.pcper.com/article.php?aid=669&type=expert detailing how to zero out the SSD’s. This page: http://www.pcper.com/article.php?aid=669&type=expert&pid=6 also provides a download link to the correct version of HDDErase that will work with these Intel SSDs.

    So I went to work on zeroing out these SSD’s… Afterwards, I re-ran the HDTune tests and here are the resultant graphs:

    SSD1-R-AFTER

    SSD1-R (above)

    SSD2-R-AFTER

    SSD1-R (above)

    Now those are some nice smooth read graphs!

    SSD1-W-AFTER

    SSD1-W (above)

    SSD2-W-AFTER

    SSD2-W (above)

    Still a little spikey on writes but not bad at all! I’ll take it!

    SSD-STRIPE-R-AFTER

    STRIPE-R+(above) write caching turned on in Intel Matrix Storage Manager for this striped volume

    nice and smooth, average 479.3MB/s reads, WOW!

    SSD-STRIPE-W-AFTER

    STRIPE-W+(above) write caching turned on in Intel Matrix Storage Manager for this striped volume

    not bad at all! average 148MB/s for writes, now we’re talking!

    -----------------------------------

    Now what does this all mean??? For peak write AND read performance, we’re going to have to image our hard drive, secure erase each SSD, and then put the image back on our stripe-set. This really sux! The good news is that newer SSDs including Gen 2 of Intel X25-Ms will support TRIM which will automatically zero out the pages on the SSD that are no longer in use at more opportune times than when you want to write to that page. Windows 7 has TRIM built in, so you should be all set after some number of firmware and windows updates have been completed down the road when TRIM will be working in all its glory… Until then, image, secure erase, un-image for peak performance. Oh and don’t forget, each time you write or zero out a page on your SSD, that is one less time you will be able to write to it before it fails. They don’t call this the bleeding edge for nuthin, folks!

    June 06

    Forgot to enable AHCI on your Windows 7 RC (or Vista) for your SSD?

     
    I was doing some reading tonight an found info implying that unless your SATA controller is set to AHCI or RAID mode (BIOS setting), performance improving things like NCQ and Trim do not work even if your SSD or hard drive (that was so 2008!) has those features available.
     
    So, of course, changing this BIOS setting and expecting everything to work is just asking a bit too much (what do you think we're talking about, a Mac?). After making this BIOS change, you will soon see a beautiful blue screen of death otherwise known as BSOD. When this occurs, you will likely be googling around for some solution to the problem (after you change that BIOS setting back and reboot) or maybe you'll try the new Microsoft Bing (I didn't). In any event, hopefully you will find this blog entry or the link I will provide that should solve your problem.
     
    http://support.microsoft.com/kb/922976 will show you how to make a registry entry change that will likely solve the problem for you. At least it did for me...
     
    Here is the relevant info from the link above:
     
    To resolve this issue, enable the AHCI driver in the registry before you change the SATA mode of the boot drive. To do this, follow these steps:
    1. Exit all Windows-based programs.
    2. Click Start, type regedit in the Start Search box, and then press ENTER.
    3. If you receive the User Account Control dialog box, click Continue.
    4. Locate and then click the following registry subkey:
      HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Msahci
    5. In the right pane, right-click Start in the Name column, and then click Modify.
    6. In the Value data box, type 0, and then click OK.
    7. On the File menu, click Exit to close Registry Editor.

    After doing this, reboot, get into the BIOS, change back to AHCI mode and eventually you will be able to login to Windows (i.e. no BSOD). At this time, Windows will figure out that is needs to install drivers for your fancy new AHCI controller that replaced your old legacy controller (which of course forces you to reboot one more time) and then you are all set.

    At least this is how it went down for me with Windows 7 RC (BTW: Windows users can be happy and proud again with Windows 7, Mac ain't got nuthing on you no more...at least until Snow Leopard comes out, then we'll just have to see...)

     

    May 26

    iPhone on Verizon?

    I am using an iPhone on T-Mobile but am very hesitant to switch to the new iPhone coming out this summer on ATT even though I really want to. Why? It costs more per month and has only slightly better coverage than T-Mobile. Also, some of the restrictions on ATT just really rub me the wrong way. For example, SlingPlayer can only operate with WIFI? HUH? How can they charge me for “unlimited” 3G internet access and deny me the ability to use my SlingPlayer unless I am connected to WIFI? I used SlingPlayer years ago on T-Mobile with my window mobile phone and it worked just fine (no extra charge BTW)!

    There is a rumor that Verizon may soon have an iPhone. Now that, my friend, is a differentiator! I could (and I may) still switch from T-Mobile to ATT in order to get the new iPhone this summer even though I will be paying more for less monthly. But I would JUMP at the chance to switch to Verizon if I could have the new iPhone on their network. I would even pay MORE per month than ATT charges. Why? Ubiquitous signal coverage (OK, maybe not ubiquitous but heck Verizon has coverage even in the western PA mountains that I visit every few years). Better signal strength indoors (isn’t this where most of us use our phones anyway?). 80 million customers...make that 80 million and 1, I hope. Why does this matter? FREE MOBILE TO MOBILE. And besides that, when they acquired AllTel, the created a “My Faves” like plan that T-Mobile has. With this plan, you can pretty much have UNLIMITED calling minutes while paying for the least minutes plan under certain conditions (ask me for details if interested, you'll need Google Voice previously known as GrandCentral).

    OK, I am done ranting for today. I feel better now. C’mon Verizon, step up to the plate (QUICK)!
    April 23

    asp Checkbox css style on the input element

     
    when ASP.NET renders an <asp:Checkbox... /> it renders HTML similar to this:
     
    <span><input type="checkbox" ... /></span>
     
    When you want to specify the height of the checkbox for example. You would think something like this would do the trick:
     

    checkBox.Height = Unit.Pixel(12); // this is needed for IE8

    This actually does the trick for IE8 but not for IE6. Now this is rendered:
     
    <span style="display:inline-block;height:12px;"><input type="checkbox" ...  /></span>
     
    For IE6, the following code must be used:
     

    button.InputAttributes[

    "style"] = "height: 12px"; // this is needed for IE6
    button.InputAttributes["height"] = "12px"; // this is needed for IE6
    button.Height = Unit.Pixel(12); // this is needed for IE8

    This actually does the trick for both IE8 and IE6. Finally this is rendered:

    <span style="display:inline-block;height:12px;"><input type="checkbox" height="12px" ... /></span>

    This was a PIA for me to figure out, I hope this helps you if you run into a similar formatting issue with ASP.NET Checkbox controls.

     
    January 06

    WinMerge integration with TortoiseSVN

     
    sometimes, the magic command used to integrate WinMerge as the Diff Viewer for TortoiseSVN gets lost. I aways forget what that command is so I am documenting it here (so I don't have to look it up again):
     
    TortoiseSVN -> Settings -> External Programs -> Diff Viewer
     
    Click "External" and enter the following (adjusted with your path to WinMerge, if necessary):
     
    C:\Program Files (x86)\WinMerge\WinMergeU.exe -e -x -ub -dl %bname -dr %yname %base %mine
     
    If you want this automatically setup for you. Install WinMerge AFTER you install TortoiseSVN and check the box that says integrate with TortoiseSVN.
     
    I feel better already...
     
     
    November 10

    Windows Update fails to install updates

     

    Today I ran into a computer where windows update would download updates from Windows Update and would start the installation process before finally failing to install any of the updates. No reason was given for the failure. Looking at the update history, where one would expect to find the error, did not even have the update attempt listed.

    First, where to find more information about the errors related to Windows Update: c:\windows\WindowsUpdate.txt. You might find some clues regarding the problems there. I Google'd on a couple of errors listed there and found the following solution for the problem I was experiencing.

    Solution (re-register these dlls):

    regsvr32.exe c:\windows\system32\wuweb.dll
    regsvr32.exe c:\windows\system32\wups2.dll
    regsvr32.exe c:\windows\system32\wups.dll
    regsvr32.exe c:\windows\system32\wucltui.dll
    regsvr32.exe c:\windows\system32\wuaueng1.dll
    regsvr32.exe c:\windows\system32\wuaueng.dll
    regsvr32.exe c:\windows\system32\wuapi.dll

    Next, restart the Automatic Updates server (you might have to reboot to get Windows Update working in IE).

    This problem was on an XP system for me but I have heard this also affects other Windows OS's.

    October 29

    Adaptec 3805 RAID Controller and ASUS P5Q-E Motherboard

     
    Here is what works:
     
    • QX6700 2.66 GHz extreme overclocked to 2.93 via 11 Muliplier in BIOS
    • ASUS P5Q-E BIOS 1406
    • OCZ OCZ2VU80016GQ 16GB RAM
    • Adaptec 3805 Firmware version 15753 (you'll need this version of the driver as well)
    • WESTERN DIGITAL WD10EACS 1TB SATA 7200 RPM 16MB Hard Drive (8 of them)
    • Windows 2008 server (also Windows 2003 server)

    now make sure you have these versions of the firmware (especially the Adaptec firmware/driver). This caused me many nights of troubleshooting to get the Adaptec RAID controller to work. The symptom was the following messages printed on the screen after the controller completed loading:

    • No Int 13 drives to support
    • BIOS not installed!
    • Not enough space to copy PCI option ROM

    The final symptom/problem is that even though I was typing CTRL-A to get into the configuration manager for the controller. The configuration manager would never load.

    At various times with various motherboards, I had one or more of the above error messages from the Adaptec controller. In each case, soon after these error messages, the computer would continuously beep.

    After many night of trying many different BIOS settings, moving the card to different slots, buying another 3805 thinking that the first one was bad...the problem was the firmware for the 3805 that came with it from the factory would not work on my new motherboard P5Q-E (it wouldn't work on my previous motherboard either P5K-E). This was very confusing to me since my old computer with the same P5K-E motherboard had a 3805 in it and is working just fine -- no BIOS setting changes required.

    Finally, I noticed that my old computer's 3805 had an old version of the Adaptec firmware on it and the new ones had a more recent but not latest firmware version on it. I doubted this could be the problem, aren't all new firmware versions better than older versions? Perhaps the software developer in me was forcing this assumption on me...

    Now the problem was actually upgrading the firmware on the controller. I had to install a floppy drive in this system. The firmware is too big to fit on one floppy. Nicely, Adaptec had broken it into two firmware files and afu.exe. I put afu.exe and the first smaller file on the first floppy and then the second BIG firmware file on the second (it barely fit). Finally, I booted an old windows 98 floppy, put in the floppy containing afu and ran it. Eventually it ask me for the second file. Finally, it upgraded the firmware on the adaptec RAID controller.

    Holding my breath, I anxiously rebooted the computer, waited for the Adaptec messages to show on my screen, and hit CTRL-A to enter the array configuration manager.

    VOILA! Life is good! Thank you Jesus!

    You MUST use the corresponding Adaptec driver version instead of the drivers that will be installed automatically by Windows 2008 (or 2003) in order for everything to work properly. The only way to do this is to install the driver manually:

    Device Manager/SCSI and RAID Controllers/Adaptec RAID 3805/Update driver
    1) no, don't search for software
    2) install from a list or specific location
    3) don't search, I will choose the driver to install
    4) have disk
    5) select AMD64 subdirectory to get X64 drivers

    Take-aways:

    1. if it don't work, check your BIOS version and Firmware versions
    2. if it does work, don't change your BIOS version or your Firmware versions, you could end up with an incompatible version (uh, if it ain't broke, don't fix it!)

    if this helps you, paypal me $1 cause I have an extra 3805 now that I have to pay for and they ain't cheap!

    August 22

    Mac Remote Desktop Connection Display Resolution Limitations

    When you are editing preferences for your Mac Remote Desktop Connection, there are limited display resolutions you can choose for the remote desktop size.  You can also choose “Fit to Window” but this scales the window instead of changing the screen resolution which sux.

    However, there is a way to define your own preferred resolution (assuming the windows box you are connecting to can support it). Use TextEdit to change the saved rdp file for the connection you want to change. See below for an example where I set the resolution to 3820x1150 (this works good with my Dual Head2Go on my MacBook).

    rdp

    On another note, Visual Studio development via VMWare or Parallels is just not fast enough for me on my MacBook Pro. Even though it probably does not significantly reduce productivity, it is frustrating to have to wait for windows to pop-up and builds to complete. I’m just not used to having to wait for anything in my dev environment. I’m thinking this is due to running on a laptop not due to running in a VM on Mac since running a VM on my Win server is actually acceptable. The good news, I suppose, is that this means there is no reason for me to get a high-performance MacBook/MBP when I give this one to my wife the end of this year. Maybe even a MacBook Air will do...

    July 24

    Indexed View in SQL Server 2005

    Indexed Views can be now used in any version of SQL 2005 but will not get used automatically by the query optimizer unless you’re running enterprise edition (SQL2000 required the enterprise or developer edition to even create them).

    Example (not a good one since this query is not very expensive):

    IF EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[INDEXED_VIEW_TEST]'))
    DROP VIEW [dbo].[INDEXED_VIEW_TEST]
    GO

    CREATE VIEW [dbo].[INDEXED_VIEW_TEST] WITH SCHEMABINDING
    AS
    SELECT  A.[Name],
                      AMC.[AudienceID],
                      AMC.[CompanyLocations],
                      AMC.[Sections],
                      AMC.[Departments],
                      AMC.[JobTitles],
                      AMC.[CustomFieldValue1],
                      AMC.[CustomFieldValue2],
                      AMC.[CustomFieldValue3],
                      AMC.[CustomFieldValue4],
                      AMC.[CustomFieldValue5]
    FROM    [dbo].[AudienceMemberCriteria] AMC
    INNER JOIN [dbo].[Audiences] A ON AMC.[AudienceID] = A.[ID]
    GO

    IF EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[INDEXED_VIEW_TEST]') AND name = N'IDX_INDEXED_VIEW_TEST')
    DROP INDEX [IDX_INDEXED_VIEW_TEST] ON [dbo].[INDEXED_VIEW_TEST] WITH ( ONLINE = OFF )
    GO

    CREATE UNIQUE CLUSTERED INDEX [IDX_INDEXED_VIEW_TEST] ON [dbo].[INDEXED_VIEW_TEST]  ([AudienceID] ASC)
    GO

    -- this query does not use the index, this is query 1 below
    SELECT * FROM INDEXED_VIEW_TEST
    GO

    -- this query DOES use the index, this is query 2 below
    SELECT * FROM INDEXED_VIEW_TEST WITH (noexpand)
    GO

    You can see that query 2 is much more efficient. Query 1 takes 70% of total time to run while Query 2 takes only 30% of the time. Also, there is no table join for Query 2.

    clip_image002

    July 21

    iPhone (not 3G) with OS 2.0 works on T-Mobile

    I can vouch that this actually works: http://lifehacker.com/398906/jailbreak-iphone-20-with-pwnagetool

    I used the previous version (2.0) of the pwnagetool (macOS version) with no problems whatsoever (there is a newer release) on one iPhone with 2.0, one iPhone with 1.1.4 and on one with 1.1.3 installed prior to using this tool.

    I created only 1 patched 2.0 ipsw file using this tool. And then I restored the phones from DFU mode using this same ipsw file. You have to hold down option and click restore so iTunes will prompt you for the file to use. It’s all documented on the lifehacker link above.

    Finally, I recommend getting the $19.99/month Blackberry Internet Service from T-Mobile. Then all you have to do is set the APN for the network on the iPhone to “wap.voicestream.com” and everything will work, yup Safari, YouTube, Google maps, App Store, … it all just works.

    Good Luck, all I can say it worked for me with three gen 1 iPhones. This does NOT work with the new 3G phones. Wife and kids are happy with them. I gotta get one more so I can pwn it for me!

    I love the pineapple dudes!

    July 13

    MagicJack

    I’ve had MagicJack for over 6 months now and have been using it as a second line at my house. I must admit that I am underwhelmed. Sound quality is not great, neither when using a headset on my computer with it nor with a regular phone plugged into it. It probably sounds as good as a cell phone with 4 out of 5 bars except for all the occasional burps and squeeks that come from MagicJack. Skype sound quality is much better. However, the price of MagicJack is really cheap. There is no free ride, you get what you pay for. I guess the real test will be when renewal comes up, will I renew it? Don’t know yet…

    Anyway, I’ve found that it works better for me just to connect it to a regular phone and not use the headset on the computer where MagicJack is being run. So I have it hooked up to my Windows 2003 X64 Server and am running it as a service. This works as well as any other scenario for me. I found instructions on how to run MagicJack as a Windows Service here, it’s really pretty easy to do.

    July 07

    Firefox 3 hits the spot!

    I have been using Firefox 3 on both PC and Mac since soon after it was released and have to say that I am pretty impressed. As a developer (and also when I am testing) I need to have “display a notification about every script error” turned on in IE so that I know if any JavaScript errors occur on the code I'm slinging. Unfortunately, this causes errors to pop up regularly when I am using IE on other sites that I read or search which really sux. So now I use Firefox for searching and reading and IE for developing/testing which is much better.

    Also, there are some pretty cool add-ons to make Google stuff much easier to look at. Google (gmail, reader, gcal, …) stuff usually works really well but it’s just plain ugly. The add-ons: Better Gmail2, Better GCal, Better GReader make these things look much better and add more functionality.

    I have to admit that I do like FireFox better than Safari as well and it is nice to have all the same shortcut keys, add-ons, etc on both platforms.

    July 02

    C# Boxing and Unboxing (Cast, AS, Convert, Parse, TryParse)

    There are a lot of ways to do type casting in C#. Hopefully, these examples can help you decide what the best method for each situation you run into…

    const int theInt = 12;
    const string theString = "fred";
    
    object boxedInt = theInt;               // value of theInt is boxed into boxedInt
    object boxedString = theString;         // value of theString is boxed into boxedString
    
    ///////////////////////////////////////////////////////////////////////////////////////////
    // this method of unboxing throws exception on failure
    ///////////////////////////////////////////////////////////////////////////////////////////
    int unboxedI = (int)boxedInt;           // unbox boxedInt to get the int value
    Console.WriteLine("(int) boxedInt={0}, isNull={1}", unboxedI, (unboxedI == null));
    
    string unboxedString = (string) boxedString; // unbox boxedString to get the string value
    Console.WriteLine("(string) boxedString={0}, isNull={1}", unboxedString, (unboxedString == null));
    
    try
    {
        unboxedString = (string) boxedInt;
    } catch (Exception e)
    {
        Console.WriteLine("(string) boxedInt={0}", e.Message);
    }
    
    ///////////////////////////////////////////////////////////////////////////////////////////
    // this method of unboxing returns null on failure (can't do value types with as)
    // unboxedI = boxedInt as int; is a compiler error, int is a value type
    ///////////////////////////////////////////////////////////////////////////////////////////
    unboxedString = boxedString as string;  // returns value of boxed string
    Console.WriteLine("boxedString as string={0}, isNull={1}", unboxedString, (unboxedString == null));
    unboxedString = boxedInt as string;     // returns null
    Console.WriteLine("boxedInt as string={0}, isNull={1}", unboxedString, (unboxedString == null));
    
    ///////////////////////////////////////////////////////////////////////////////////////////
    // this method of unboxing throws exception when it can't determine how to convert
    ///////////////////////////////////////////////////////////////////////////////////////////
    unboxedI = Convert.ToInt32(boxedInt);
    Console.WriteLine("Convert.ToInt32(boxedInt)={0}, isNull={1}", unboxedI, (unboxedI == null));
    unboxedString = Convert.ToString(boxedString);
    Console.WriteLine("Convert.ToString(boxedString)={0}, isNull={1}", unboxedString, (unboxedString == null));
    try
    {
        unboxedI = Convert.ToInt32(boxedString);
    }
    catch (Exception e)
    {
        Console.WriteLine("Convert.ToInt32(boxedString)={0}", e.Message);
    }
    unboxedString = Convert.ToString(boxedInt);
    Console.WriteLine("Convert.ToString(boxedInt)={0}, isNull={1}", unboxedString, (unboxedString == null));
    
    ///////////////////////////////////////////////////////////////////////////////////////////
    // this method of unboxing throws exception when it can't determine how to convert
    ///////////////////////////////////////////////////////////////////////////////////////////
    unboxedI = Int32.Parse(boxedInt.ToString());
    Console.WriteLine("Int32.Parse(boxedInt.ToString())={0}, isNull={1}", unboxedI, (unboxedI == null));
    unboxedString = boxedString.ToString();
    Console.WriteLine("boxedString.ToString()={0}, isNull={1}", unboxedString, (unboxedString == null));
    try
    {
        unboxedI = Int32.Parse(boxedString.ToString());
    }
    catch (Exception e)
    {
        Console.WriteLine("Int32.Parse(boxedString.ToString())={0}", e.Message);
    }
    unboxedString = boxedInt.ToString();
    Console.WriteLine("boxedInt.ToString()={0}, isNull={1}", unboxedString, (unboxedString == null));
    
    ///////////////////////////////////////////////////////////////////////////////////////////
    // this method of unboxing allows you to define the behavior, throw an exception if you want.
    ///////////////////////////////////////////////////////////////////////////////////////////
    int? nullableUnboxedI = null;
    if (Int32.TryParse(boxedInt.ToString(), out unboxedI)) nullableUnboxedI = unboxedI;
    Console.WriteLine("Int32.TryParse(boxedInt.ToString())={0}, isNull={1}", nullableUnboxedI, (nullableUnboxedI == null));
    
    nullableUnboxedI = null;
    if (Int32.TryParse(boxedString.ToString(), out unboxedI)) nullableUnboxedI = unboxedI;
    Console.WriteLine("Int32.TryParse(boxedString.ToString())={0}, isNull={1}", nullableUnboxedI, (nullableUnboxedI == null));
    
    // TryParse for string is simply ".ToString()" ;-). There is a TryParse for Boolean, Byte, Char, DateTime,
    // DateTimeOffset, Decimal, Double, Int16, Int32, Int64, IPAddress, SByte, Single, TimeSpan, UInt16, UInt32, UInt64 
    
    /* results of running this code copied from the console window:
        (int) boxedInt=12, isNull=False
        (string) boxedString=fred, isNull=False
        (string) boxedInt=Unable to cast object of type 'System.Int32' to type 'System.String'.
        boxedString as string=fred, isNull=False
        boxedInt as string=, isNull=True
        Convert.ToInt32(boxedInt)=12, isNull=False
        Convert.ToString(boxedString)=fred, isNull=False
        Convert.ToInt32(boxedString)=Input string was not in a correct format.
        Convert.ToString(boxedInt)=12, isNull=False
        Int32.Parse(boxedInt.ToString())=12, isNull=False
        boxedString.ToString()=fred, isNull=False
        Int32.Parse(boxedString.ToString())=Input string was not in a correct format.
        boxedInt.ToString()=12, isNull=False
        Int32.TryParse(boxedInt.ToString())=12, isNull=False
        Int32.TryParse(boxedString.ToString())=, isNull=True
        Press any key to continue . . .
    */
    
    July 01

    TryParse anyone?

    Hey, I just found out this new TryParse method for objects that can be Parsed in .NET 2.0. It still falls a little short of what I need but it is a step in the right direction. For example, I have a bunch of utilities methods where I pass in an object and “try” to convert it to a float or int or datetime, … If the conversion fails, I’ll return the “default value”. If the conversion succeeds, I’ll return the parsed value. Here’s an example:

    public static float GetFloatFromObject(object objToFloat, float defaultValue)
            {
                float retValue;
                try
                {
                    retValue = Convert.ToSingle(objToFloat.ToString());
                }
                catch (Exception)
                {
                    retValue = defaultValue;
                }
                return retValue;
            }

    Now with .Net 2.0, I can do this instead:

    public static float GetFloatFromObject(object objToFloat, float defaultValue)
    {
        float retValue;

        if ((objToFloat == null) || (!float.TryParse(objToFloat.ToString(), out retValue))) retValue = defaultValue;

        return retValue;
    }

    Not only is this less code, but I hear it performs much better since there is no exception handling during the process.

    Now, of course, if you want to do something when the parse would fail, you’ll need to do it the old fashioned way and do that something when you catch the exception.

    June 26

    I want an iPhone but I need T-Mobile

     

    Yeah, you want an iPhone so do I but what I need is T-Mobile@Home. Why?

    1) For $10/month, all calls made at home via WIFI on my cell phone are free, they don’t count against my minutes! (WIFI phone from T-Mobile required)

    2) You can reduce your plan minutes because of #1. Save money by getting a cheaper monthly plan to make up for adding $10/month.

    3) #1 also solves the problem of less than ideal signal strength inside my house since the phone will be using WIFI instead of GSM.

    4) All T-Mobile plans are cheaper than ATT.

    5) T-Mobile SMS/MMS/… monthly fees are less than ATT.

    6) T-Mobile internet monthly fees are less than ATT.

    7) If you really want an unlimited plan, it is still MUCH cheaper with T-Mobile. $99/month for first phone, $49/month for phones 2-5 (ATT is $99/phone for all phones). If you get unlimited, there is little point in T-Mobile@Home except for #3.

    8) After July 11, I suspect there will be millions of iPhones (1.0) on eBay for a good price that can unlocked to use on T-Mobile when I need to look kool (sp). I won’t be able to use the iPhone with HotSpot@Home though (c’mon hackers). But when I hit the road, I’ll just put my SIM card in the iPhone…

    9) You can get rid of your POTS landline! Save even more money!

    10) there has to be 10 items in this list right??? Because I can!

    What about iPhone 2.0? 3G speed? etc? I guess you get what you pay for!

    Man, I hope T-Mobile reads this and gives me a free Android phone to beta test for this free advertising!!!

    June 04

    Resharper 4.0 Release Candidate available!


      I doubt that I could write code anymore without this thing

      Try it, you'll like it!  http://www.jetbrains.com/resharper/beta/beta.html

    May 20

    SVN Rocks! (Subversion)

     

    We had been using NGSource for a long time so that we can develop code over the internet using a solid version control system. As most people who have tried it know, Visual SourceSafe performs terribly over the internet. NGSource works pretty well but it has its warts as all good software does... A few months ago, we decided to switch to using Subversion instead which is an open source version control system. We have never looked back! We install TortoiseSVN on our developer boxes and use Hamachi to create a VPN that all developers connect to. It works great! One thing that I thought I would miss but don’t is the integration that NGSource does with the Visual Studio IDE: it shows what is checked out by you or others and permits you to do all your source control operations inside Visual Studio. However, this is both a blessing and a curse. It is hard to argue with its convenience however, this integration also slows everything down significantly and occasionally causes random burps and hangs. Now we just do whatever we want unhindered by the source control system and use windows explorer to update or commit our changes to the source control system. An extra step indeed but the speed and robustness of this process is worth the effort. Another great feature is forward compatibility, since TortoiseSVN is not a plug-in to Visual Studio, I don't have to worry that a Service Pack or upgrade to a new version of Visual Studio will break my source control system.

     

    Now there is one big paradigm shift between typical source control systems and SVN. With typical (old-fashioned) source control systems, you lock a file when you want to work on it and no one else can modify the file while you have it locked. SVN does "optimistic locking". It keeps track of who changes what and when you commit your changes, it will automatically merge any conflicts that it can or ask you to help merge the conflicts. In reality, it does a good job of automatically merging and it is a pretty rare occurrence for files to end up in the conflicted state where you need to manually merge the conflicts (although we do try to assign work so that different developers are working on different parts of the code as much as possible). This brings me to my next tip! After installing TortoiseSVN, install WinMerge. It will automatically attach itself to TortoiseSVN so that it gets used for differencing files. It is most excellent!

    February 20

    Caught sleeping in Math class again...

     

    There are two ways to round a number using the Math.Round method in .NET 2.0:

     

    ·         MidPointRounding.AwayFromZero - When a number is halfway between two others, it is rounded toward the nearest number that is away from zero.

    ·         MidPointRounding.ToEven - When a number is halfway between two others, it is rounded toward the nearest even number. 

     

    MidPointRounding.ToEven is the DEFAULT!

     

    This means that:

     

    Math.Round(4.5) will return 4

    Match.Round(5.5) will return 6

     

    HUH?

     

    My old math -- would expect the following results:

    4.5 -> 5

    5.5 -> 6

     

    In order to get my expected results, the following calls need to be made:

     

    Math.Round(4.5, MidPointRounding.AwayFromZero) will return 5

    Math.Round(5.5, MidPointRounding.AwayFromZero) will return 6

     

    According to the doc, the ToEven is the IEEE standard. I guess I know I am old when rounding no longer works as I would expect, unless I was sleeping during that class...

    November 06

    Installing SQL Server Management Studio when you already have Management Studio Express installed!

    Why would you need to have the full-blown version of Management Studio when you can just download and install the Express version of Managment Studio you ask? Because I want to be able to use SQL Refactor from Red-Gate. I don't really need a full-blown install of SQL Server for my development purposes, all I really want is SQL Express and the full blown Management Studio in my Developer VM.

    I got this info from here (kudos to him) but I wanted to put a copy in my blog so the next time I need to do this I won't have to search for it...

    After you uninstall SSMS Express:

    1. Click Start, and then click Control Panel.
    2. Double-click Add or Remove Programs.
    3. In the list of installed programs, click Microsoft SQL Server 2005, and then click Change.
    4. On the Component Selection page, select Workstation components, and then click Next.
    5. Click Next.
    6. On the Change or Remove Instance page, click Change Installed Components.
    7. Click Client Components, and then select Entire Feature will be Unavailable.
    8. Click Next.
    9. Click Install.

    Now you should be able to install from the full-blown edition of SQL Server Management Studio (and subsequently SQL Refactor!)