Tuesday, December 30, 2008

ASP.NET MVC or Web Forms?

Nick Berardi has just written a great post ASP.NET MVC vs. ASP.NET Web Forms that compares the pros and cons of using Web Forms or MVC when developing a web application with ASP.NET. The part that I like most about this blog post is the worksheet scoring system that he's created to provide an objective way of choosing between the two.

Thursday, December 25, 2008

Mix 09 TenK Challenge

I've written a Silverlight control to enter into the Mix09 TenK Challenge. This is my entry: BMI Calculator and here is the main gallery page with all the entries.

At the time of writing this (9am on Christmas day) I'd finished the project and checked the file sizes. 21,438 bytes - about double what I'm aloud. I'm now going to remove all comments, spaces etc. and refactor all variables down to a couple of letters each.

During the exercise of reducing the code size I did a number of things:

  1. I refactored my code. I went through everything I had written and found fragments of unused or unnecessary code and removed them. I also discovered all sorts of size inefficiencies in what I'd done and during this process reduced the code size, made it more maintainable and in the process faster. This came as a bit of a surprise because I didn't realize how much of an improvement refactoring would make to my code and as an exercise has opened my eyes to doing this more often.
  2. I used VS2008's refactor feature to rename variables and function names to single and two letter names.
  3. In the XAML files I considered each attribute and if I was explicitly declaring the default value then I removed it. This had probably happened when I changed from the default to a specific value and then back again.
  4. In all files I removed newlines, replaced tabs with spaces and then replaced double spaces with single spaces. The last operation (replacing double spaces with single spaces) needed to be run four to five times to remove all the redundant spaces.

In the end I managed to reduce the code to 9,617 bytes. I also learned a ton about Silverlight in the process, especially how little code is really needed in the App.xaml and App.xaml.cs files.

There was another feature that I wanted to put into this calculator which I'd left out because I suspected that it wouldn't have fitted in. With hindsight that appears to have been the correct decision as I don't think the remaining few hundred bytes would have been sufficient space.

Links to posts about the Mix 09 TenK Challenge:

Tamir Khason - How to write a program without XAML
Bill Reiss - Thoughts on the MIX 10K challenge
Jobi Joy - Tips used to limit code size 

 

Sunday, December 14, 2008

Oxite

Oxite is a "simple blog engine written using ASP.NET MVC."

At the time of writing this I am hosting this blog using Grafitti CMS. If I was about to start this blog I would select Oxite because:

  1. It uses ASP.NET MVC which I'm familiar with and have done some work on.
  2. It's open source so I can change it easily to suit my needs.

The pain points in moving to Oxite would be:

  1. Converting the blog content and comments to Oxite, data store and format.
  2. Writing link redirection to preserve page rank and avoid broken links.

Friday, December 12, 2008

Silverlight Toolkit December 2008

I've just upgraded the Silverlight Toolkit libraries that I'm using to the December 2008 version.

When reocmpilling my Online Calculators project I discovered that the DynamicSeries type had disappeared but it wasn't listed in the changes section so I had to hunt around for it. I compiled the Toolkit's source and then searched all the files for DynamicSeries and found it left in one of the comments and it appears to have been replaced by the DataPointSeries class.

Replacing the DynamicSeries references with DataPointSeries references got the project to compile and it appears to run correctly.

There has, however been a performance degredation in the auto-updating of the charts in the Mortgage Calculator so I haven't deployed this yet. I'll try and take a look at what's happening and try and optimize my code and see if I can get it back to the current speed before deploying the new libraries.

Wednesday, December 10, 2008

Finding an embedded resource name

I was trying to load an embedded resource into a Silverlight DLL using this code:
 
            System.Reflection.Assembly asm = Assembly.GetExecutingAssembly();
            System.IO.Stream xmlStream = asm.GetManifestResourceStream("Namespace.Filename.xml");
            XDocument xDoc = XDocument.Load(xmlStream);
 
However, the xmlStream was null and hence an exception. I had mistyped the "Namespace.Filename.xml" part of the code but couldn't see what part I'd mistyped. To fix this I changed the code to this:
 
            System.Reflection.Assembly asm = Assembly.GetExecutingAssembly();
            System.IO.Stream xmlStream = asm.GetManifestResourceStream("Namespace.Filename.xml");
            string[] names = asm.GetManifestResourceNames();
            XDocument xDoc = XDocument.Load(xmlStream);
 
and put a break point on the last line and inspected the names array to find the correct name. It was late at night and I was tired so a copy/paste finally resolved to the correct name.

Monday, December 1, 2008

Silverlight Finally

I've finally had a chance to do a bit of work on coming up to speed with Silverlight and thought I'd share my findings and get some feedback.

I've created a Calculator site with a couple (so far) of pages written in Silverlight:
Mortgage Calculator
Temperature Converter

I've been trying to compare Silverlight to its alternatives of Javascript and Flex/Flash. A difficult comparison because I've never used Flex/Flash and my Javascript isn't that great.

Findings from my point of view and my skill set:

Advantages of Silverlight

  1. Language is C# so zero learning curve on that part.
  2. Tools (VS2008 and Blend) are very good - Intellisense made the learning curve less steep for the Silverlight library, architecture and controls.
  3. Web resources good - I hit plenty of small problems (like hosting this on Server 2003) but after a bit of searching found answers to all problems.
  4. Speed - those 2 pages are fairly responsive for what is going on behind them but it's possible that Javascript/Flex could execute at same or better speed. Anybody care to comment on that?

Disadvantages of Silverlight

  1. So far I've only been able to get those pages to work in IE and Chrome and can't get them to work in Firefox.
  2. Opera is not supported yet.
  3. Not everyone will want to install the Silverlight plugin to view those pages.

Wednesday, November 26, 2008

WCF Tracing with SvcTraceViewer

I had a problem with an WCF Service that I'd written that was reading from an MSMQ and would blow up if the message was larger than 64K. Once I'd tracked down the exception that was being thrown (QuotaExceededException) a quick search on Google with "wcf quotaexceededexception" landed me on Hugo Batista's blog site and his WCF: maxReceivedMessageSize and QuotaExceededException post which was exactly what I was experiencing and this solved the problem.

This, however, did not solve the problem of how incredibly difficult I found it to log that QuotaExceededException exception. Like Hugo Batista I'd tried to catch the UnhandledException event from the AppDomain but this was unsuccessful.

Eventually I discovered that I could turn on Message Logging and Tracing in the App.config file and then use the SvcTraceViewer application to look at those files. This worked a charm and the tools make it pretty easy.

First you need to edit the App.config file but Visual Studio 2008 has a utility that makes this very easy for WCF. Right click on the App.config file and you will see an option "Edit WCF Configuration." This brings up the Microsoft Service Configuration Editor which makes editing this much easier. In the Configuration section on the left hand side click on Diagnostics and then click on the links "Enable MessageLogging" and "Enable Tracing" and set the locations for the log files.

Now run the errant web service and once it's faulted the channel open the error file with SvcTraceViewer. I found SvcTraceViewer in the "C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\" folder on my XP machine. The tracelog is where you'll find the warnings etc.

Tuesday, November 25, 2008

Jon Skeet is better than Chuck Norris

 A coworker of mine brought the Jon Skeet Facts question to my attention a few days ago and I laughed out aloud when I read it. Subsequently Jeff Atwood blogged about it in Stack Overflow Is you.

The icing on the cake, for me at least, is Jon Skeet's sense of humor in writing the accepted answer in the third person. Very funny.

Friday, November 21, 2008

The difference between Tempuri and Tempura

If you've ever worked with a web service that started off life being generated by a Microsoft tool then you've probably seen the namespace http://tempuri.org/. I've seen this for years and I know it well. I also know that you're supposed to change it immediately but that hardly anybody does.

Until today, I had no idea why it was called http://tempuri.org/. I thought that maybe it was some fictional company like Contoso that a Japanese employee from  Microsoft who loved tempura style deep-fried cooking had made up to stick in the namespace.

The along came a friend of mine and pronounced it as Temp URI, and suddenly it all fell into place.

Monday, November 17, 2008

Microsoft JScript runtime error object expected with jQuery

I was trying to get a simple piece of jQuery to work and was running up against this error in Internet Explorer (IE):

Microsoft JScript runtime error: object expected

The problem turned out to be that I wasn't referencing jQuery to the correct path. The trick I discovered, if you're using Visual Studio, is to just drag the JavaScript file from the Solution Explorer into the <head> element on your page and it will insert the correct reference for you.

UPDATE (9 July 2009):

I am referencing jQuery from the Google CDN now:

<script src="http://www.google.com/jsapi"></script>
    <script>
        google.load("jquery", "1.3.2");
        google.load("jqueryui", "1.7.2");
</script>

Using this technique will also get rid of this error and improve performance.

The first reference to jQuery (1.3.2) is for the core jQuery library. The second reference to (1.7.2) is for the optional jQuery UI library that you will only need if you are using the UI components/elements of the jQuery library. If you are using jQuery to manipulate the DOM only then you won't need the UI reference.

 

Sunday, November 16, 2008

NoIndex NoFollow

I was just using Google to search Stack Overflow and came up with the following search results:




If you click on the second, third, or fourth items in the search results and then search the page for the term jscript you will find that it's not there. That's because when Google indexes the "hottest" part of Stack Overflow the jscript question was on the page but this is a volatile page and the links from this page change frequently.

Personally I find it annoying when I arrive at an dynamic index page on a site (via Google) only to find that the search term has subsequently been bumped off the list.

Should we do anything about this? And if so, what can we do about this?

First off, I think that you should not have Google index this page. If you have this keyword on your site then let Google focus its results on the page that has this keyword and that talks about this keyword. Spreading a keyword widely across a site is going to dilute its effectiveness and degrade user experience when they visit the site looking for that information.

On the Google Toolbar bar in IE there's the option to enable the happy and unhappy faces to vote on a page when you land there. I don't believe that Google uses this information however it does give me satisfaction when I land on an indexed page which doesn't have the search keyword on it to be able to click the unhappy face.

The obvious exception to this is if you have a stable, non-volatile index which will always have the keyword on it. Although this will not be as effective as landing the user on the content page because it will still require the user to find the link on the landing page and click through.

The way that I accomplish this in C# on my ASP.NET web sites is to set the robots meta tag as such:
 <META NAME="ROBOTS" CONTENT="NOINDEX">

I do this by using a common base class for all my pages. Here's a subset of the code from the base class:
public class CommonPageBase : System.Web.UI.Page
{
    public void SetNoIndexNoFollow()
    {
        SetRobots("NOINDEX,NOFOLLOW");
    }
    public void SetNoIndex()
    {
        SetRobots("NOINDEX");
    }
    public void SetNoFollow()
    {
        SetRobots("NOFOLLOW");
    }
    private void SetRobots(string content)
    {
        HtmlMeta robotsMeta = new HtmlMeta();
        robotsMeta.Name = "ROBOTS";
        robotsMeta.Content = content;
        Page.Header.Controls.Add(robotsMeta);
    }
}

Then in the code behind page for the .aspx page the Page_Load function will look something like this:
public partial class MyPage : CommonPageBase
{
    protected void Page_Load(object sender, EventArgs e)
    {
        SetNoIndex();
    }
}

You may of course want to make the call to the SetNoIndex() function conditional on an isVolatileIndex type variable. 

Podcasts for Developers

I'm now struggling to find good developer focused podcasts to listen to. When I first discovered Hansel Minutes there were already 109 archived episodes so that kept me busy for several months. Thank you Scott Hanselman. At about the time that I ran out of Hansel Minute podcasts, Jeff Atwood and Joel Spolsky started their Stack Overflow Podcasts. At first I was not that impressed (the first couple of episodes) but I have subsequently become a big fan and it has now pushed Hansel Minutes into second place on my favorites list. This is probably because of Spolsky's arrogant and confrontational personality (this is a good thing) along with his sense of humor. He doesn't hold punches when verbally sparring with Atwood. Although Carl Franklin now makes rare appearances on Hansel Minutes when the two of them were on the air they were too polite to each other to make the conversation as engaging as the Spolsky/Atwood combo. This is a relative comparison though - don't misunderstand me because I still think that their conversations are A-grade and would listen to them anytime.

I've been working my way through the "My developer podcast" (link removed because broker) list on Code de Mora but haven't heard anything on that list that really engages me like the other two do. I've also found a number of podcasts on IT Conversations which I've downloaded but not listened to yet.

So here is my current list of podcasts in favorite order (to be edited when I find more or my preference changes):

Scott Hanselman created a List of Podcasts for .NET Programmers on 9 Feb 2009. He also said "If you've created a list of YOUR favorite .NET Podcasts, send me a link to your blog and I'll add it here" - however, if I did that then you'd end up in an infinite loop.

jQuery Select Notes

class: e.g. <p class="me"> text</p>
jQuery: $('.me')

id: e.g. <p id="me">text</p>
jQuery: $('#me')

element: e.g. <p>text</p>
jQuery: $('p')

elements inside id's: e.g. <ul id="me"><li><a>...
jQuery: $('#me a') will select all the anchor elements <a> under that <ul> tag.

elements inside elements (child tags): e.g. <html><p>text</p></html>
jQuery: $('body > p')

elements next to elements (siblings)
jQuery: $('p + div')

elements with attributes: e.g. <img src="..." alt="..." /> 
jQuery: $('img[alt]') will select all <img> tags with an alt attribute
$('a[href]') will select all anchor tags with an href attribute and thereby exclude named anchors: e.g. <a name="jumpToMyLocation">

elements with attributes having specific values
exact value: $('input[type=text]') will select all input tags with an attribute of type set to text.
starts with: $('a[href^=mailto:]') will select all anchor tags that have an href attribute set to a value that starts with 'mailto:'.
ends with: $('a[href$=html]') will select all anchor tags that have an href attribute set to a value that ends with '.html'.
contains: $('a[href*=content]') will select all anchor tags that have an href attribute set to a value that contains the text 'content'.

filter with : (colon)
$('tr:odd') will filter the <tr> selection from a table by the odd rows using a zero based index for the <tr> tags.
$('a:not([href$=html]') will filter the anchor selection by excluding all anchor tags with href attributes that end in 'html'.
$('li:has(a)') will filter the <li> selection by <li> elements that have <a> elements as child elements. This will result in a collection of <li> tags and not <a> tags.
$('a:contains(click here)') will filter the anchor tags which have the text 'click here'.
$('div:hidden') will get all the <div> tags that are hidden.
$('div:visible') opposite of $('div:hidden')

Friday, November 14, 2008

Team Wiki

We have a team wiki for our development team. It's sometimes difficult to decided what goes into the wiki.

I have a rule that after I've been asked the same question three times by a co-worker I put it in the wiki.

How do you decide what goes in your team wiki?

Hacking attempt

I've noticed the following trailing URL logged as an error by IP's of dubious origin on one of my sites:

/++++++++++++++++++++++++++++++++++++++++++Result:+registered+(registering+only+mode+is+ON);

The hacker-bot attempted the same URL about 20 times using proxies from the UK, Netherlands, Australia, Poland, USA, Japan, China, Malaysia, and Germany. It had multiple different proxies in almost all those countries so each of the 20 IP's were unique.

I'm wondering what security hole are they trying to exploit?

Tuesday, November 11, 2008

Cloud Computing Defined

When the internet is included in an architecture diagram of a system it is almost always depicted as a cloud. The cloud refers to applications and operating systems running on remote computers accessible locally and usually via the web.

Previously cloud computing was called:

  • Software as a Service (SaaS)
  • Client / Server
  • Time Sharing

Should I have called this mini-post "there is nothing new under the sun?"

Monday, November 10, 2008

LINQ to XML Resources

This is a collection of LINQ to XML Resources that I've found useful.

Daniel Moth has a great diagram and explanation of the System.Xml.Linq namespace.

Hooked on LINQ's five-minute overview.

Microsoft's LINQ to XML Overview.

Hansel Minutes LINQ to XML podcast.

Joseph Albahari's excellent LINQPad utility can be used to visualize the workings of LINQ to XML. Plenty of samples in this application.

Scott Guthrie on how to build a custom RSS Feed Reader with LINQ to XML.

Typed XML programming by using LINQ to XSD.

Transforming with LINQ to XML.

 

Sunday, November 9, 2008

lsass.exe and SQL Server pegging CPU at 100%

Had an unusual problem with an MS Server 2003 today. The CPU was being pegged at 100% every 15 seconds for about 12 to 14 seconds. When I examined the Processes with Task Manager it showed that lsass.exe was the culprit and that its accomplices were sqlservr.exe and w3wp.exe.

This happened shortly after a deployment of a web site to the server that had been built on an x64 Server (2008) but deployed to an x86 Server (2003) - so I was considering this as a possible problem however I knew that I'd compiled the ASP.NET web app to target any CPU.

I found numerous references on the web to lsass.exe causing problems and also found this hotfix from Microsoft which I installed but it did not help: http://support.microsoft.com/kb/939268/ (when I say that it did not help I mean that it did not immediately fix the problem although it could have later added to a resolution by being there.)

After further hunting and examining event logs and server logs and disabling and stop and starting differenct web sites on the server I narrowed the problem down to one particular web site. This web site is an ASP.NET web app but also has a ASP Snitz forum in one of the sub-folders.

I tried taking the web site offline with the App_Offline.htm file and noticed that unlike when I stopped the web app the problem was still there. So I checked the forum and noticed that App_Offline only works with the ASP.NET part of the site and not the ASP part of the site.

This gave me a breakthrough in the hunt for a solution because I'd managed to separate the ASP and ASP.NET code and determined that it was the former. So I deleted the App_Offline.htm file and went into the forum admin page and took down the forum. The CPU usage immediately returned to normal and the pegging at 100% by lsass.exe and the others stopped.

Even though I'd isolated the problem to a small area I still didn't know what was causing this. Now this is the frustrating part: I switched the forum back online and the problem dissappeared. The CPU usage is back to normal and the problem gone. Although I'm happy that that problem's gone I'm frustrated that I don't know what caused it and fearful that it will return again.

Remember that I rebooted this server after I installed the MS KB patch metioned above which would have obviously stopped and restarted the web app and the forum code as well so I don't think that it was just a matter of stopping and starting it.

Friday, November 7, 2008

VS2008 Object Test Bench

My amazingly talented co-worker Dan Esparza showed me the Object Test Bench in VS2008 which I never knew about until today. Looks like a productive tool:

If you want to test an object and invoke its methods then you can instantiate a class directly from the VS2008 IDE and call its methods.

  • Open the Class View in your project and right click on a class and select Create Instance... and then select the constructor from the sub-menu (there'll only be one option if you don't have a constructor or a single constructor).
  • The Object Test Bench window will open and the instantiated object will be in that window.
  • Right click the object and select a method to invoke on it.
  • If you have a break-point on the object then execution will stop there and you can inspect the values etc.

The only oddity I've seen so far is that it will only work on class in the start-up project. More info here...

Wednesday, November 5, 2008

Heisenbug

I was listening to Scott Hanselman's MSR at PDC podcast and he discussed a tool called Chess which is designed to work with Team MSTest in VS2008 to track down Heisenbugs. I'd never heard of this type of bug being called a Heisenbug before but have experienced it plenty. Simply stated, a Heisenbug is a bug that dissappears when the code is run through the debugger.

The name Heisenbug appropriately comes from the Heisenberg uncertainty principle which states that the position and momentum of a particle cannot both be known simultaneously.

I loved Hanselman's Heisenberg joke:

Heisenberg get's pulled over by the police.
Officer: "Do you know how fast you were going?"
Heisenberg: "No, but I know exactly where I am."

Sunday, November 2, 2008

CPUID Hardware Monitor

Ultramaroon put me on to the CPUID Hardware Monitor. This is how my machine is currently running:


Thursday, October 30, 2008

The difference between Java and Javascript

 I recently posted the following question on Stack Overflow: What's the difference between Javascript and Java? and received some great answers.

Greg Hewgill's answer of "Java and Javascript are similar like Car and Carpet are similar" was spot on and amusing. Shog9's answer was hillarious.

The other answers citing the differences listed a few I hadn't thought of but essentially there's almost nothing to tie these two languages together but for part of a word and some curly braces.

But that's not what this is about. What I'm finding fascinating about Stack Overflow is asking questions that I already know the answer to and discovering a whole bunch of answers and opinions that I hadn't thought of and further broadening my knowledge. There're some very clever people hanging out there - I wish I was one of them.

Thursday, October 23, 2008

Running VPN on a VM

Just been doing some testing on running VPN on a VM and on the host OS. The host in this case is Server 2008 x64 and the VM software is Hyper-V and the guest VM is Vista x64.

As expected, the OS running VPN takes on the IP address of the VPN while host or guest will continue to use the original IP that you were previously connected to. Obviously the VPN is running over your original IP to get to the VPN but to the outside world this is the IP that you're using.

Wednesday, October 22, 2008

String Reverse in C#

 I had to write a string reverse function today and wasn't happy with my initial (basic) function so I posted it on Stack Overflow to see what other algorithms that developers might come up with. My restriction was that it had to be in C# 2.0 and so I couldn't use LINQ. Out of curiosity I decided to do a performance test on each of the functions and while I was at it I threw in the LINQ equivalent to see how it would perform. For the test of a 500 character string I looped each function 100,000 times and for the test of a 10 character string I looped the functions 10,000,000 times.
These are the functions that I tested:
// string concatenation with for loop
public string ReverseA(string text)
{
    char[] cArray = text.ToCharArray();
    string reverse = String.Empty;
    for (int i = cArray.Length - 1; i > -1; i--)
    {
        reverse += cArray[i];
    }
    return reverse;
}

// Array.Reverse function
public string ReverseB(string text)
{
    char[] charArray = text.ToCharArray();
    Array.Reverse(charArray);
    return new string(charArray);
}

// push/pop Stack<>
public string ReverseC(string text)
{
    Stack resultStack = new Stack();
    foreach (char c in text)
    {
        resultStack.Push(c);
    }

    StringBuilder sb = new StringBuilder();
    while (resultStack.Count > 0)
    {
        sb.Append(resultStack.Pop());
    }
    return sb.ToString();
}

// LINQ
public string ReverseD(string text)
{
    return new string(text.ToCharArray().Reverse().ToArray());
}

// StringBuilder
public string ReverseE(string text)
{
    char[] cArray = text.ToCharArray();
    StringBuilder reverse = new StringBuilder();
    for (int i = cArray.Length - 1; i > -1; i--)
    {
        reverse.Append(cArray[i]);
    }
    return reverse.ToString();
}


 


What surprised me was how poorley LINQ did on the short string compared to the others.
You may also find the rudimentary test harness that I put together interesting:
delegate string ReverseDelegate(string text);

public void RunPerformance()
{
    int loopCount = 10000000;
    int stringSize = 100;
    string[] reverseTextArray = Enumerable.Repeat("abcde", stringSize).ToArray();
    string reverseText = String.Join("", reverseTextArray);
    // reverseText = "1234567890";
    DateTime startTime, endTime;
   
    ReverseDelegate[] reverseFunc = new ReverseDelegate[5];
    reverseFunc[0] = ReverseA;
    reverseFunc[1] = ReverseB;
    reverseFunc[2] = ReverseC;
    reverseFunc[3] = ReverseD;
    reverseFunc[4] = ReverseE;

    AssertThatFunctionsWorkCorrectly(reverseFunc);

    TimeSpan[] reverseTime = new TimeSpan[reverseFunc.Length];

    for (int i = 0; i < reverseFunc.Length; i++)
    {
        startTime = DateTime.Now;
        for (int j = 0; j < loopCount; j++)
        {
            reverseFunc[i](reverseText);
        }
        endTime = DateTime.Now;
        reverseTime[i] = endTime - startTime;
        Console.WriteLine("{0}/{2} took {1}", i, reverseTime[i], reverseFunc[i].Method);
    }

    Console.WriteLine("break point");
}

private void AssertThatFunctionsWorkCorrectly(ReverseDelegate[] reverseFunc)
{
    string test = "abcdefghi";
    string expected = "ihgfedcba";
    for(int i=0; i

Monday, October 20, 2008

Phoenix Startup Weekend Sunday 19 Oct 2008

The last day was good. We had more direction about what we wanted to achieve in that day and what it would take to achieve it. The team is very good and it did not appear that we took a lot of effort to make it come together. The prototype that we put together worked and played the player. The puppet master pulled the strings and web sites updated, text messages were sent and answer machines responded with the appropriate distress calls.

Dan, a Microsoft rep played the game towards the late afternoon and apart from some minor glitches which were nothing to do with our technology he succeeded in playing the game and accomplishing the mission which was do defuse a fake bomb (actually an iPhone). He also gave us a glowing recommendation at the sum-up at the end. The audience also had plenty of questions which was a good sign.

Sunday, October 19, 2008

Phoenix Startup Weekend Saturday 18 Oct 2008

The group started with a strategic meeting about where we wanted to get to and also the expanse and potential of the Alternate Reality Game project. There were a lot of good ideas and the potential for this product could be huge. Monetizing it without the player being offended appears to be fairly easy inasmuch as the oportunities for doing such appear wide spread.

Problems faced during the day:

  • The network at Gangplank (our hosts) was very slow. This could have been because the amount of traffic was not what it was set-up for.
  • The four developers on the team were split between the Java world and .NET worlds meaning that two of the developers could not work to their full potential.
  • The marketers/implementers were more focused on what the potential of the product could be and should have probably spent more time looking at what we can produce in the span of 1.5 days.

These were minor set backs and I hope that we get a working prototype finished by tomorrow evening.

Saturday, October 18, 2008

Phoenix Startup Weekend Friday Night 17 Oct 2008

The Phoenix Startup Weekend kicked off to a good start on Friday evening. Pizza and beer wer served. About 30 ideas were pitched.

I pitched two which got 3 and 2 votes respectively and were therefore dropped from the ideas list. The first idea was a web managed Scavenger Hunt which I didn't even vote for myself because it was very similar to the group that I eventually joined which is an Alternate Reality Game project. The second idea that I pitched was for a web based list learning system which I still think has a lot of potential but I don't think that I pitched it very well.

Of the 30 or so projects pitched about 6 to 8 of them went on to have groups formed to discuss their potential. One of the interesting fallouts from this stage of development was the importance of having developers buy into your idea. There was a small group of people who were very enthusiastic about their project but there were no developers that had joined that group. I believe that the decided to disband and redistribute.

After joining my group It was immediately obvious that there were a lot of very inteligent, motivated and highly talented people around me. This weekend promises to be at the very least a fantastic education.

Sunday, October 12, 2008

.NET Directory Notes

The documentation for the XmlWriter.Create Method (string) function has ArgumentNullException as the only exception that will be thrown for this function. I've found that System.IO.DirectoryNotFoundException can also be thrown here.

The AppDomain.CurrentDomain.BaseDirectory does not terminate with a back slash if you are running a unit test - you need to add this if you're going to append further directories. To make the using of AppDomain.CurrentDomain.BaseDirectory work in both unit tests and production code you might want to create a property to access the AppDomain.CurrentDomain.BaseDirectory that looks something like this:

string SafeBaseDirectory
{
            get
            {
                return AppDomain.CurrentDomain.BaseDirectory.EndsWith(@"\") ? 
                                AppDomain.CurrentDomain.BaseDirectory :
                                AppDomain.CurrentDomain.BaseDirectory + @"\";
            }
}

Friday, October 10, 2008

C# Keywords

C# Keywords

abstract
as
base
bool
break
byte
case
catch
char
checked
class
const
continue
decimal
default
delegate
do
double
else
enum
event
explicit
extern
false
finally
fixed
float
for
foreach
goto
if
implicit
in
int
interface
internal
is
lock
long
namespace
new
null
object
operator
out
override
params
private
protected
public
readonly
ref
return
sbyte
sealed
short
sizeof
stackalloc
static
string
struct
switch
this
throw
true
try
typeof
uint
ulong
unchecked
unsafe
ushort
using
virtual
void
volatile
while

Contextual Keywords

from
get
group
into
join
let
orderby
partial (method)
partial (type)
select
set
value
var
where (generic type constraint)
where (query clause)
yield

Tuesday, October 7, 2008

LINQ to XML Notes

Some notes on LINQ to XML

  • All LINQ to XML objects inherit from XObject.
  • All LINQ to XML objects except XAttribute inherit from XNode which directly inherits from XObject.
  • Using XDocument is optional. (XDocument wraps an XElement object and adds to it.)
  • Both XDocument and XElement have static methods Load and Parse to load XML.
  • Load() can build an X-DOM from a TextReader, XmlReader, a file or a URI (such as a web service or RSS feed).
  • Parse can build an X-DOM from a fragment of XML in a string.

Monday, October 6, 2008

How does the Luhn Test work?

The code to find credit cards in a block of text is available on GitHub: Credit Card

The Luhn Test or Luhn Algorithm is a test of a series of numbers to determine if they could be a valid credit card. The algorithm is fairly simple and I'll demonstrate it with 4 digits.

The number to test: 4 - 5 - 6 - 7

Step 1: Starting from the right, double every second digit:

8 - 5 - 12 - 7

Step 2: If the result of the doubling ends up with a 2 digit number then add those 2 digits together.

8 - 5 - 3 - 7

Step 3: Add all the digits together.

8 + 5 + 3 + 7 = 23

Step 4: Mod the number against 10.

23 % 10 = 3

Step 5: Is the number exactly divisible by 10?

i.e. does 3 equal 0?

If it is (exactly divisible by 10) then it passes the Luhn Test and could be a credit card number.

Ask a simple question

I asked on Stack Overflow why i++ followed by ++i would compile but ++i++ would not compile under C#. When I saw the answer it was obvious why it was a simple question. I hadn't spent very long thinking about it and breaking the problem down.

What I found interesting though was that the question was immediately voted down and had a -2 vote after a few minutes. I checked again an hour later and it was back to zero.

I originally titled this post as "ask a stupid question" before realizing that the question wasn't stupid but one that many programmers could have. It was well answered and I am the wiser for it and I hope someone else is as well.

Based on this micro analysis, I wonder if Stack Overflow has a few elitist members who are fast to the draw and vote down anything that's a simple-to-solve problem.

Best practices for creating websites in IIS 6.0

 Omar AL Zabir has a good write-up on Best practices for creating websites in IIS 6.0.

Friday, October 3, 2008

Stopping a Hyper-V VM that refuses to stop

I posted this question on the Microsoft Tech Forums: I have a Vista (x64 Ultimate) VM that refuses to stop. (Host is Server 2008 x64.)  I've tried using the hard stop but it remains in the state of Stopping. How do I stop it from here?

And received this (great) answer from Stephen Edgar:

If you grab Sysinternals Process Monitor you can check each VMWP.EXE Process (Virtual Machine Worker Process) and Select 'Properties' and each process will have a reference in the 'Command Line' section of the properties dialogue which refers to the VM's GUID which can be found for each VM by examining the configuration files contained in C:\ProgramData\Microsoft\Windows\Hyper-V\Virtual Machines and then just kill the approriate VMWP.EXE Instance and that should kill that VM without affecting any of your other currently running VM's.

This is the second time that I've had this problem with Hyper-V and I have no doubt that it won't be the last. Thanks Stephen!

Thursday, October 2, 2008

Buying a PCI bus card on Craigslist

 Here's a question that I can't find an answer to. I've found a PCI bus card (TV tuner) on Craigslist that I want to buy. The seller says that they've got rid of their PC and now have a Mac and so don't have a need for this card. How can I find out if this card is working without lugging a PC around to his house and installing it then and there before buying it?

Wednesday, October 1, 2008

How not to leave breadcrumbs

I was listening to Jeff Atwood and Joel Spolsky's podcast from a couple of weeks ago (podcast 22) and Jeff mentioned the Fight Club rule (The first rule of fight club is you do not talk about fight club) and how Stack Overflow is not intended to be a site that discusses itself. i.e. The first rule of Stack Overflow is you do not talk about Stack Overflow on Stack Overflow. This is also the reason that I'm not posting this on Stack Overflow and instead posting it here.

One of the reasons that Jeff doesn't want Stack Overflow discussion on Stack Overflow is that he doesn't want Google et al indexing Stack Overflow pages that discuss how the site works. When a user finds Stack Overflow through a Google search it will hopefully bring them to a page with a question and solution to a problem that they might be trying to solve. Not to a meta-discussion.

So how do you solve this problem. In my opinion fairly easily: You dynamically create the robots.txt file that's in the root of the site each time it's requested (instead of having a static one). You then query the database for all questions that are marked with the "stackoverflow" tag and add their URL's to the disallow section of the robots.txt content that you're going to return to the requesting search-bot. That way the meta-discussion won't be indexed by the search-bot.

After typing that I thought of what is probably an even easier solution. When you retrieve and construct the page from the DB just add the <META name="robots" content="NOINDEX,NOFOLLOW" /> to the <head> tag in the page if it has a "stackoverflow" tag and Google won't index that page.

Not sure why I got so carried away with dynamically generating the robots.txt page/file...

Inheritance Question

In C#, which Console.WriteLine() would be hit?
Without consulting your compiler, take a look at the code and then vote your answer.

    public class A
    {
        public void Bar(int n)
        {
            Console.WriteLine("A.Bar");
        }
    }

    public class B : A
    {
        public void Bar(double n)
        {
            Console.WriteLine("B.Bar");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            B b = new B();
            b.Bar(5);
        }
    }

Vote your answer now before you read any further.

 

At the time of writing this the general consensus was wrong. Note - I was also wrong when I took a guess at what the answer is.

The answer is that B.Bar will be hit and not A.Bar

My theory behind why this happens is that I think that C# walks the inheritance tree from the outer class inwards and each time that it finds a matching function name it then checks to see if all of the parameters can be cast to the first method that it finds. If so, it then uses that method.

With the help of a friend, I then tested this on Java. It turns out that Java does not behave in this manner. The Java compiler, I'm guessing takes 2 walks of the inheritance tree. The first time it looks for an exact match. The second time it attempts to do a cast. So the answer for a Java compiler would be a print of A.Bar. However, this question was asking about C#.

Here are the results of the poll

EDIT: Name mangling - that's how it does it in Java and C++. It creates a unique name for each function call based on its function name and the parameter types. I just remembered that.

Tuesday, September 30, 2008

Micropoll

 I recently discovered MicroPoll through Scott Hanselman's site and liked the format so I thought that I'd try it out with an inline survey on this blog to see how well it works.

 

Here are the results of the poll:

Polls Powered By MicroPoll

Monday, September 29, 2008

Google Chrome Installer Error 1625

Just tried to install Google Chrome on Server 2008 and received the following error from Google Chrome Installer:

Installation failed. Component ChromeGears failed to install. Detailed message: The installer encountered error 1625: The installation is forbidden by system policy. Contact your system administrator.

Solved: Ran the ChromeSetup.exe file as administrator and everything installed okay. Open the containing folder of the setup file and right click install file (ChromeSetup.exe) and select "Run as Administrator."

Friday, September 26, 2008

Hosts file locked (read-only) on Server 2008

I was trying to edit the HOSTS file on Windows Server 2008 with Notepad++ but after editing it wouldn't let me save it with a "Save failed" - "Please check whether if this file is opened in another program" (the ...whether if... is their message not my typo).

Anyhow, didn't turn out to be read-only as I initially thought or another process as suggested (I did try stopping several services to see if that would help) but instead it turned out to be the fact that I hadn't started Notepad++ as administrator.

I don't understand why I need to run Notepad++ as administrator to edit the HOSTS file but aparently I do. I'm sure that it's just a matter of getting used to this new Vista style UAC that I assume is the underpinning of the security model in Server 2008.

To run Notepad++ (or any other program) as an administrator just right click on the application and select "Run As Administrator."

Thursday, September 25, 2008

Double URL Encoding

Sometimes you know the answer but you still want to see it happen to make yourself happy.

Question: If you encode some text and then encode it again is it encoded inside encoded?
Answer: Yes
Question: What happens if you decode it twice as well?
Answer: You get back to the original unecoded text

Here is a snippet of text that demonstrates it using C# in .NET. You need to include the System.Web library.

            string stringWithAmp = "&";
            Console.WriteLine(stringWithAmp); // "&"
            stringWithAmp = HttpUtility.HtmlEncode(stringWithAmp);
            Console.WriteLine(stringWithAmp); // "&amp;"
            stringWithAmp = HttpUtility.HtmlEncode(stringWithAmp);
            Console.WriteLine(stringWithAmp); // "&amp;amp;"
            stringWithAmp = HttpUtility.HtmlDecode(stringWithAmp);
            Console.WriteLine(stringWithAmp); // "&amp;"
            stringWithAmp = HttpUtility.HtmlDecode(stringWithAmp);
            Console.WriteLine(stringWithAmp); // "&"
 

Monday, September 22, 2008

The Second Law of Continuous Integration

From this post on Jeremy Miller's blog:

Jeremy's First Law of Continuous Integration:

If you check in very often and/or first, you can make merge conflicts be someone else's problem.

The Second Law:

If someone did sneak in a check in between two of your check ins then the merge problem will be small because the number of changes you've done will be small if you're checking in frequently. 

The Law of Encouragement:

Point this out to your coworkers to make all changes between check ins as small as possible so that you don't waste half a day on merging.

Reinstall of Vista and Ubuntu Virtual Machines

Over the weekend I was trying to install a few things on my Vista and Ubuntu Linux virtual machines. Both are 64bit VM's runing under Server 2008 x64 with Hyper-V. I ended up in the situation where the Vista machine lost its network connection and then wouldn't power down. It got to the point of almost powering down and then hung. I tried all sorts of things to sovle this problem but was unsuccessful. This state of the VM was also causing Server 2008 to blue screen on about every fifth reboot and when I looked at the log files they always related to the VM. I also tried to start and stop the Linux VM (which had been in a stopped state all this time) and the same thing happened inasmuch as I couldn't power it down.

In the end I uninstalled the Hyper-V role in Server 2008 and deleted the VM machines from the hard disk. Here are my notes about what I learned and the mistakes that I made.

  1. Download and get the ISO ready before creating a virtual machine.
  2. When setting up a VM that does not have Integrated Components select a legacy network adapter.
  3. Uncheck the box that says "start VM when this wizard finished" (or somthing like that).
  4. Once you've created the VM open the settings and check them all. Check that there's a single network adapter and that it's a legacy adapter.
  5. As soon as you've run the install of the operating system and it's completed its initial updates take a snapshot of the VM.
  6. Take regular snapshots of the VM after each operation that you perform.

 

Saturday, September 20, 2008

Hyper-V with Vista x64 and Ubuntu Linux Desktop x64

Notes about setting up Vista x64 as a guest virtual machine on my Windows Server 2008 x64 machine.

The installation ran relatively smoothly. I pointed the Hyper-V wizard at the Vista x64 iso and the installation happened.

The only tricky part was getting the network connection up and running. On Hyper-V, under settings for Vista x64 I had to add a Legacy Network Adapter and set that to my point to my Virtual Network. I also left the MAC address at Dynamic and unchecked the "Enable virtual Lan identification" check box.

When setting up Ubuntu Linux Desktop x64 I had to use the same strategy with setting a Legacy adapter to get it to hook onto the network.

I read somewhere that it's the x64 part of these operating systems that cause you to have to use the legacy adapter. I'm right on the edge of my knowledge at the moment as I've never done any of this before so take what you read with a pinch of salt. I now believe that it's because the Integration Components (IC's) are not available for these OS's.

Did Borland throw away the C++ compiler market?

Back in the days of DOS to Windows when the market was about 60% DOS and 40% Windows (early 1990's) Borland was the first to the market (when compared to Microsoft) with a C++ compiler. Shortly after this compiler came out they also brought out 2 libraries. One was called OWL which stood for Object Windows Library and I forget the name of the other but it might have been TF for Turbo Framework. OWL was a library for writing Windows apps and TF was a windowing library for DOS.

During that period a lot of programmers were trying to target both platforms to maximize the number of platforms their software ran on - an obvious goal and is still in practise today. What I thought was crazy was they fact that OWL and TF had completely unrelated API's. In other words, there was no way you could easily target 2 platforms with this compiler. At the time I thought that it was ludicrous and I've never seen a good explanation for it.

A short while later Microsoft brought out the first of its Visual C++ compilers with MFC (Microsoft Foundation Classes) and walked away with the market. MFC never targeted DOS but by then I believe that the PC market share had reached a 50/50 point and it was obvious that DOS was doomed. Had Borland brought out a single API that could target both systems I believe that they would have survived for many more years in that market and may have even been a competitor today.

Friday, September 19, 2008

How Stack Overflow is helping me

Jeff Atwood from Coding Horror has recently moved Stack Overflow to public beta. According to my user profile, as of today I've been using it for 35 days and I've found it amazingly useful.

When you're coding there is often a question that has an easy answer but you don't know the answer off the top of your head and your initial searches on Google don't reveal it. I have found that a well worded question on Stack Overflow will usually yield an answer within a few minutes. More complex and difficult questions sometimes take longer.

This is the equivalent of turning around to your 2 or 3 colleagues who are sitting near to you and saying "hey, how do you create a C# continue statement in Ruby?" except you're saying it to 1,000 compatriots on Stack Overflow.

I'm very impressed.

TIPS:

  1. When asking your question be precise.
  2. Ask a question that has a definite answer that will help you move on to the next problem when answered.
  3. Give (as brief as possible) some background to your problem if relevant. Your language (don't assume that everyone codes in C#), OS, platform.
  4. Return to the question and mark one as correct - if appropriate and also vote up any other answers that were useful.
  5. Thank the people that answered your questions.

Wednesday, September 17, 2008

From power on to a working system

I've just built myself a new computer. It has 8GB of RAM, a fast processor and plenty of fast disk space and is running Server 2008 Enterprise. What I'm doing here is recording how long it takes from power on to windows loading to the sign-on screen. Because the system is new and fresh this time should currently be the shortest time that the computer will ever take to perform this task.

I intend to come back to this post and add more times in the months (years) to come and see how much the system slows time as I add bagage to it.

17 Sep 2008 - power to windows: 30 seconds; windows to logon: 40 seconds (Checked build of Server 2008 - later uninstalled)

On new installation of retail version of Server 2008:

18 Sep 2008 - power to windows: 30 seconds; windows to logon: 27 seconds

Installation failed for component Microsoft .NET Framework 2.0SP1

I'm trying to install .NET 3.5 SP1 onto Server 2008 Enterprise and I'm getting this error:

Microsoft .NET Framework 2.0SP1 (x64) (CBS): [2] Error: Installation failed for component Microsoft .NET Framework 2.0SP1 (x64) (CBS). MSI returned error code 1

On inspection of the folders it appears that .NET 3.0 is already installed C:/Windows/Microsoft.NET/Framework/ here. Mystery still not solved...

Tuesday, September 16, 2008

String Contains From Array with Extension Method

Using LINQ, I wanted to find all lines in a file that didn't have any of the strings in an array of "exclude" strings that I had. This is the function that I came up with to handle that case once I'd read in the lines from the file.

        static string[] NotInSecondArray(string[] first, string[] exclude)
        {
            return first.Where(a => !a.Contains(exclude)).ToArray();
        }

However, the string Contains function doesn't take an array so you need to add something like this:

    public static class MyExtensions
    {
        public static bool Contains(this String str, string[] inArray)
        {
            foreach (string s in inArray)
            {
                if (str.Contains(s))
                {
                    return true;
                }
            }
            return false;
        }
    }

Time Estimates

When someone asks me how long it will take me to do something my brain immediately gives me the best case scenario. If I'm being realistic I double that because of all the unforseens that make it longer.

Last Saturday I went to Fry's Electronics with Rob and bought all the parts for a new computer. My estimate to put this computer together was about a week using Sunday and the evenings over the next week. I was going to take my time and make sure that this first time assembly was done correctly and that I didn't break anything.

Rob being the generous genuis that he is came over on Sunday morning and before lunchtime the machine was running and I was installing an OS. This is probably the only multi-hour project that I've estimated that came in so far ahead of the best case scenario. However, this wouldn't of been the case if I'd done it by myself.

Thanks for all your help Rob.

Thursday, September 11, 2008

System.IO.Packaging

I'm experimenting with the Open XML Format SDK 1.0 and to get to the System.IO.Packaging namespace I needed to add a reference to the WindowsBase assembly. I would never have guessed that the System.IO.Packaging namespace was in there and will probably forget in a short while so I'm leaving myself this note here. 

More notes:

The WordProcessingDocument class is in the DocumentFormat.OpenXml.Packaging namespace in the DocumentFormat.OpenXml assembly.

Wednesday, September 10, 2008

AZGroups Forward/Back Button History and jQuery

 Two very good talks this evening 9 Sep 2008 at AZGroups. Thanks to Rob Bagby for staying behind and keeping the conference room open for us.

Scott Cate talked about a new control in SP1 of ASP.NET 3.5, the server side of an Ajax Forward/Back Button history. Scott's code for this demo and many of his other demos can be downloaded from http://www.codeplex.com/ScottCateAjax/

The main snippets of wisdom that I took away from this talk were:

  • 2 new (I think that they're new) attributes to the <asp:ScriptManager> tag which EnableHistory (which you need to set to true to enable the history of the back and forward buttons) and EnableSecureHistoryState whch defaults to true and does not need to be set unless you want human readable text to be on the URL and hackable which may be the case for an intranet or other URL's that you would like to enable human hackability.
  • In your page's OnInit() event you need to wire up the ScriptManager's Navigate event handler where the correct page is set on a paged control when you revisit the page using the navigation buttons.
  • The grid's pageindexchanging and sorting events also need to be added as handlers which is where the history points are set.

So to summarize: Set history points while navigating the grid using the sorting or paging controls on the grid. Restore the grid to those history points in the ScriptManager1_Navigate event when using the back and forward buttons.

The link that's produced is a perma-link whether it's the encrypted one or the plain text link and will return you to the correct page and sort setting that the grid had.

Rob Richardson gave a good talk on jQuery. His blog post about this talk which he gave at the Desert Code Camp can be found at jQuery - LINQ to JavaScript. There's a link on that blog post to his slides that can be downloaded.

Snippets of wisdom:

 

Sunday, September 7, 2008

Google Chrome Recent Pages

Internet Explorer and Fire Fox have a drop down arrow next to the Back (one page) and Forward (one page) arrows on the top left corner of their browsers. When you click this drop down it will list the previous pages that you've visited this session (as opposed to your history which lists pages visited in previous session as well). On Google's Chrome there is no drop down arrow. To get this list on Chrome, click and hold down the back (or forward) arrow for 2 seconds and the list will appear. A carefully hidden feature.

Friday, September 5, 2008

Gravatar

I didn't even realize that this blog/CMS system (Graffiti) supports Gravatar. Thanks to Bill Brown for alerting me to this.

If you don't know what Gravatar is then in as few words as possible: You upload an avatar to the Gravatar site and it becomes associated with your email address. If you put your email address in the email field in a comment to a blog that supports Gravatar then the blog will link your image directly from Gravatar otherwise it retrieves a unique pattern from Gravatar for your email address.

I remember reading about this on Jeff Atwood's Coding Horror blog but didn't even realize that I had it on here until I saw Bill's face popup next to his comment.

Google Chrome already in third position

Three days after Google released the Chrome Browser I took a look at how it ranked on one of my sites by looking at the Google Analytics stats from 2 Sep 2008 to 4 Sep 2008. I was very surprised to see that it's already in position number 3 but it only just pipped Opera so that's not saying much. I'll do this exercise again at the end of the month and see how the position has changed...


Tuesday, September 2, 2008

Google Chrome 0x80040508

Google Chrome has just been released (Google Chrome) and I would love to install it but I'm getting the following error:

"Download error. The downloaded file failed verification. Error code = 0x80040508"

The 475KB bootstrap install ChromeSetup.exe downloads okay but when it runs it brings up the message "Downloading Google Chrome..." and then that message.

Looking forward to finding a solution for this...

Update: Thanks to Ricardo's comment, here's an alternate download for Chrome that might solve your problem.

Thursday, August 28, 2008

Unit Testing Saves the Day

I had a fantastic unit testing experience at work today. A couple of days ago I released a DLL to production that scans some text and transforms part of the text according to certain rules. An example of this would be the text that users enter into a forum post. Users would enter [b]some text[/b] and the text processor would transform that into <b>some text</b> before writing it out to a web page.

When writing the transform DLL I created several unit test that check every possibility that I could think of especially the edge cases. It was a great aid and tool to developing a robust and well tested DLL.

Inevitably as soon as it was release there an edge case came to light that I hadn't thought of and so I had to fix the "bug" in the DLL. Finding and fixing it was an absolute pleasure.

First off I took the block of text that demonstrated the bug and created a unit test that passed this block of text to the DLL and showed that the DLL was failing. At this point I haven't touched the errant transform code. I ran all the unit tests in the solution (takes about 5 seconds) and as expected they all passed the unit test except for the new one.

I then proceeded to fix the code and when done I reran all the unit tests again. This time the new test passed. This is called red/green testing. First you see the red light because it failed. You fix the code. Then you see the green light. I believe that Scott Hanselman says that it's called grey/grey testing if you're color blind.

This approach gave me an enormous amount of confidence to release the new DLL because I know that I haven't introduced any code that will break any of the previous standard and edge cases because I've tested them all again - and in only 5 seconds. Granted that it took me several hours to write all those tests but I would have probably spent at least 2 hours retesting this DLL after this fix had I not had the unit tests to do it for me.

I consider this a great victory for unit testing and test driven development and I am finally seeing my efforts in writing unit tests pay off in time saved and robust software.

Tuesday, August 26, 2008

Stack Overflow

I've been using the Beta version of Stack Overflow and I'm very impressed. Jeff Atwood and his team have done an excellent job with this site and it's already provided me with some answers to questions that I had and those answers were furiously fast and accurate. I hope the quality and speed continues when they go live.

I've just caught up with the Hansel Minutes podcasts so I've started listening to Stack Overflow's podcasts. I've listened to the first 3 so far. To start with I wasn't that excited by them but by the end of the 3rd podcast they've started to grow on me and I can see myself listening to them on a regular basis.

Talking of podcasts for programmers, my friend and co-worker Saul Mora has just published a list of techie podcasts that he listens to.

Stop Forum Spam

I'm impressed with a site that my friend Huw Reddick recently alerted me to called Stop Forum Spam. It's a database of IP's, user name's and emails that have been used to spam forums. If you run a forum or maintain forum software then it's a great resource to query when someone's registering on your forum to try and cut down on spammers joining your forum. You can also submit spammer information to their database (manually) at this link. If, however, you're like me and hate spammers but are also very lazy then you'll want to automate this process as much as possible. Here's some C# code that will submit the spammers info for you:

        public bool SubmitForumSpammer(string ip, string username, string email, string apikey)
        {
            WebRequest req = WebRequest.Create("http://www.stopforumspam.com/add");
            string postData = String.Format("username={0}&email={1}&ip_addr={2}&api_key={3}", username, email, ip, apikey);

            byte[] send = Encoding.Default.GetBytes(postData);
            req.Method = "POST";
            req.ContentType = "application/x-www-form-urlencoded";
            req.ContentLength = send.Length;

            Stream sout = req.GetRequestStream();
            sout.Write(send, 0, send.Length);
            sout.Flush();
            sout.Close();

            WebResponse res = req.GetResponse();
            StreamReader sr = new StreamReader(res.GetResponseStream());
            string returnvalue = sr.ReadToEnd();

            return returnvalue.Contains("Data submitted successfully");
        }
 

Thursday, August 21, 2008

Unable to cast object of type 'System.Int32' to type 'System.String'

Came across an interesting situation today with the error message:  System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'

I couldn't work out how you couldn't cast an Int32 to a string? Seems impossible doesn't it?

Try this little snippet of code and you will be able to get that error:

            Hashtable groupList = new Hashtable();
            groupList.Add(11, new object());
            groupList.Add("12", new object());
            List<int> groups = groupList.Keys.Cast<string>().Select(a => Convert.ToInt32(a)).ToList();

The Hashtable accepts a string as a key in the second Add() call so it now has both int's and strings as keys. What I'm guessing though is that on a call to Add() the Hastable checks what data type for the key is. On the first call this data type is unset so it takes the data type of the first param and uses that as the data type for the key. On subsequent calls to Add() it sees that the data type for the key is set so just adds the item as an object for the key. This is just my guess and I'm sure if I took the time to look at this member function in Reflector I'd find out if I'm right or not.

Tuesday, August 19, 2008

Hashtable keys intersect with list of Int32

The problem: You have a classic Hashtable. Although the keys are strings they hold only ints. You also have a list of ints. You want to find out if any of the keys from the Hashtable are in the list of ints. How do you do this in one line of LINQ?

The solution, using LINQ, that I came up with is:

            // Setup the test data
            System.Collections.Hashtable ht = new System.Collections.Hashtable();
            ht.Add("1", new object());
            ht.Add("2", new object());

            List<int> second = new List<int>();
            second.Add(2);
            second.Add(3);

            // Query the data
            bool containsKey = ht.Keys.Cast<string>().Select(a => Convert.ToInt32(a)).ToList().Intersect(second).Count() > 0;

            // Print the result
            Console.Write("Contains Key: {0}", containsKey);
 

Monday, August 18, 2008

Startup Weekend Phoenix

Ever heard of Startup Weekend? I hadn't until just recently but there's one coming to Phoenix from 17-19 October 2008 and I've just ponied up my $40 to spend my entire weekend working on a startup. Should be interesting - I'm very excited:

http://phoenix.startupweekend.com/

Will take place at:

Gangplank HQ Offices
325 E Elliot Rd, Suite 34
Chandler, AZ 85225

Saturday, August 16, 2008

DOCX to HTML via XSLT

A friend just gave me a link to Creating a docx -> Html Preview Handler for SharePoint which has the modifications necessary for the XSLT that comes with Sharepoint to make the HTML web page show images as well as text from a Word 2007 document. I have a number of documents in .docx format that I want to make available as web pages but want to keep the originals in .docx format so that I can continue to edit and modify them. It is my idea that whenever I modify a Word 2007 (docx) document that I can just dump the new file into the App_Data folder and the site's pages will start showing the new or modified content. It should be too hard to do with this template. This is a soon-to-be-done project. I'll post a link to the site once I've got this done.

Tuesday, August 12, 2008

ASP.NET MVC Preview 3 to Preview 4

I recently upgraded a project from ASP.NET MVC Preview 3 to Preview 4. Running it in Cassini showed no problems but as soon as I published it to IIS 6 I started getting this error which I have yet to solve:

You are not authorized to view this page

You do not have permission to view this directory or page using the credentials that you supplied.


Please try the following:

  • Contact the Web site administrator if you believe you should be able to view this directory or page.
  • Click the Refresh button to try again with different credentials.

HTTP Error 401.1 - Unauthorized: Access is denied due to invalid credentials.
Internet Information Services (IIS)


Technical Information (for support personnel)

  • Go to Microsoft Product Support Services and perform a title search for the words HTTP and 401.
  • Open IIS Help, which is accessible in IIS Manager (inetmgr), and search for topics titled Authentication, Access Control, and About Custom Error Messages.

Visual Studio 2008 SP1

Visual Studio 2008 SP1

Visual Studio 2008 SP1 and Microsoft Framework 3.5 SP1 is available to download.

Monday, August 11, 2008

Rube Goldberg Machine

I regularly hear Scott Hanselman refer to a Rube Goldberg Machine on his Hansel Minutes podcast and once you hear something repeated enough times you need to look it up. From wikipedia: A Rube Goldberg machine is a deliberately over-engineered apparatus that performs a very simple task in very indirect and convoluted fashion.

Now I understand why he often compares a software project to a Rube Goldberg Machine.

Phoenix Startup Weekend 17-19 October 2008

The first Phoenix Startup Weekend will be 17-19 October 2008. It looks intense (54 hours work over a weekend) but also very interesting. I've marked this on my calendar but haven't booked yet. I'm very keen on doing this although I'm guessing that I'll be shattered by the time Monday comes around and will need to go back to work to have a break.

Friday, August 8, 2008

C# boxing and unboxing

In my quest to become a C# expert I've decided that I should be able to accurately and unambiguously define each and every C# term and keyword. As such I'm going to try and create a post about each one in my own (and quoted) words to act as my own reference to this language.

Boxing and Unboxing

From the documentation: Boxing and unboxing enable value types to be treated as objects. Boxing a value type packages it inside an instance of the Object reference type. This allows the value type to be stored on the garbage collected heap. Unboxing extracts the value type from the object.

My understanding is that the Object class internally has a boolean HasValue property which if false means that this object has a "value" of null. If it's true then a value has been assigned. I also assume that there is a Type property which represents the type of object that has been stored (such as Int32) and also an area of memory for the object itself which represents the size of the object presumably obtained from the sizeof() operator.

Stuffing a value into an Object is called boxing and this is done by means of a cast:

Int32 i = 1;
Object o = (object) i;

Retrieving the value into a strongly typed type is called unboxing and this is also done using a cast:

i = (Int32) o;

Notes

Comments welcome...

Tuesday, August 5, 2008

Copy data from local table to remote database table

I need to do this every now and then and as usual forget the syntax or what I did last time to do this. I need to copy some of the data in a table to an identically structured table on another (different) database running on another Server. I do this from SQL Server Management Studio (SSMS) 2005.

  1. Using Server Objects > Linked Servers I link the remote server to my local server. (You could also connect to remote server 1 and link to remote server 2 and do this between 2 remote servers.)
  2. If the target table has an Identity key I usually disable this by setting it to no and then after the copy I set it back to yes.
  3. The syntax to copy the data is:
    insert into [255.255.255.255].dbname.dbo.tableName
    select * from dbname.dbo.tableName where ColID=[some condition]

If the "local" DB is a remote server then precede that DB name with the IP address in square brackets as well.

Another way to do the data transfer is to specify the columns after the first tableName (in parenthesis) and instead of the * (without parenthesis) and omit the identity column and let SQL Server generate that value for you if you don't need to copy it. This is the syntax:

insert into [255.255.255.255].dbname.dbo.tableName (col1, col2, col3) select col1,col2,col3 from dbname.dbo.tableName where ColID=[some condition]

Friday, August 1, 2008

type or namespace name 'ProfileCommon' could not be found

I recently hit this compile error while converting a Visual Studio web site project to a VS2008 Web App project: The type or namespace name 'ProfileCommon' could not be found (are you missing a using directive or an assembly reference?)

Turns out that Web Applications don't support the auto generation of the ProfileCommon object like web site projects do. To get this to work install this VS addin and then add it to the build process as described here.

Sunday, July 27, 2008

7z Zip and Transfer Speed Comparison

I regularly backup my databases and transfer them from the server to a local machine. My strategy is to use the 7-Zip compression utility to compress the database first and then transfer it. A smaller file will obviously transfer faster and locally I'm going to zip it anyway to save space if I'm not using it.

Today I had a situation where I was going to use the DB once I'd transfered it so it was a matter of zipping, transferring, and then unzipping. While I watched the file zip I was surprised at how long it was taking to zip and wondered if I was gaining or losing by doing the zip-transfer-unzip steps rather than just do the transfer. So I measured what I was doing.

The file size unzipped is 47Mb and zipped is 6Mb. The transfer rate is around 12 MBS (Cox Cable).

Method 1: zip - transfer - unzip:
zip: 95 seconds
transfer: 27 seconds
unzip: 3 seconds
Total: 125 seconds

Method 2: transfer
transfer: 192 seconds

Contrary to what I thought, the zip-transfer-unzip method is about 35% faster. This would obviously scale to better performance if your connection speed is slower.

Something else that you should consider is being a good net-citizen and use less bandwidth than you need to which fits in with the results of this experiment. In fact, I think if we were charged (even partially) on the bandwidth we use instead of paying a fixed amount for an unlimited amount it would have a great impact on the web's availability.

Friday, July 25, 2008

Are there enough credit card numbers?

I was wondering if the 16 digits that most credit cards have (VISA and Mastercard et al) if you don't include American Express' 13 digit cards were enough for the world or if we'd run out of digits at some point.

If I've done my calculations correctly and based on my assumption that there are 7 billion people in the world then there are enough numbers for each person on earth to have just under 1.5 million credit cards.

I then pulled out my wallet and counted that I have 16 credit card sized items in there (some of which are credit cards) and held together they are about 1cm thick. So my next calculation was to see how fat my wallet would have to be to hold 1.5 million credit cards: 937.5 meters wide, that's almost a Km.

Casting Out Nines

I'm working on a project at the moment that involves the verification of credit card numbers. This has led to running checksums on the numbers to validate them including Luhn's algorithm.

Simply stated, Luhn's algorithm doubles every second digit (starting from the right) and then adds together all of those digits which it then mods against 10 to check for success. So if you had the sequence 2568 it would be transformed into 4-5-12-8. You would then add each digit together, the 12 would become 3 (1+2) and not be a 12. So your total is 4+5+1+2+8 = 20. Mod this against ten: 20 % 10 = 0 and if 0 then it passed the test.

In code, when computing the algorithm, you may end up with a 2-digit number after doubling it. Although you could convert it to a string and then convert each digit back to a number to add them together it's easier to subtract 9 from the doubled number which will give you the same result. 12 - 9 = 3 as does 1 + 2 = 3. This, I have just learned is called "Casting Out Nines." Cool term, I like it.

Here is the C# code that I came up with:

                int total = 0;
                bool even = false;
                for (int i = digits.Length - 1; i >= 0; i--)
                {
                    int current = digits[i];
                    if (even)
                    {
                        current *= 2;
                        if (current > 9)
                        {
                            current -= 9; // cast out nines
                        }
                    }
                    total += current;
                    even = !even;
                }