Hello there! It looks like this might be your first time to my website. You should...
Subscribe to my
RSS feed
Follow me
on Twitter.
Check out
.NET Dev Buzz

Webcast: NoSQL Movement, LINQ, and MongoDB

Tuesday, May 11, 2010 11:37:29 AM (Pacific Standard Time, UTC-08:00)

I'm happy to announce I'll be doing a free webcast in the DevelopMentor webcast series on MongoDB, .NET, LINQ, and NoRM.

NoSQL Movement, LINQ, and MongoDB
Tuesday May 25th - 11AM PST
Register here

I hope to see you there. We'll be building out a website in ASP.NET MVC with MongoDB as the back-end using LINQ. There will be plenty of code so it should be fun and educational.

Cheers!
@mkennedy

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Join me in Boston to Talk about .NET!

Thursday, March 11, 2010 1:09:49 PM (Pacific Standard Time, UTC-08:00)
I'll be in Boston, MA on March 22 to teach an open enrollment course for DevelopMentor. If you want to learn about WCF, WPF, Silverlight, LINQ, Entity Framework, and more there is still time to sign up (note the date may no longer appear on the public calendar).

   http://www.develop.com/course/new-net3-net35-linq

Mention this blog post and you'll receive a discount as well.

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Article: 10 Features in .NET 4.0 that made Me Smile

Wednesday, December 16, 2009 2:36:23 PM (Pacific Standard Time, UTC-08:00)

I recently wrote another article for DevelopMentor's Developments newsletter (not subscribed yet? see top-right of this page). This one is entitled

   10 Features in .NET 4.0 that made Me Smile

Read it on the DevelopMentor website: http://www.develop.com/tenfeaturesdotnet4

I am republishing it below for you all to enjoy on your RSS readers.

Cheers,
Michael


10 Features in .NET 4.0 that made Me Smile

I have been reviewing some of our upcoming classes at DevelopMentor this week. One of those classes, What’s New in .NET 4.0, left me excited for things to come. There are a bunch of small but wonderful features discussed in that class. I thought I’d take this opportunity to write a few of them up and share the joy. I bet some of them make you smile too.

  1. The Parallel Extensions for The .NET Framework will be built into mscorlib.dll.

    The fact that PFx will be part of the core .NET library says a lot about how much faith and support it’s getting within Microsoft. BTW, here are some really great demos for PFx in .NET 4.0.

  2. PFx introduces a new threading construct: Barrier<T>.

    Barrier lets you define rendezvous points in your code where multiple concurrent operations can automatically sync-up. Here’s an example.

  3. Code contracts.

    Code contracts allow you to assert truths about your code as if you are writing a unit test. But these assertions live within your production code and are both verified by the compiler as well as the runtime. Here’s the original research project that lead to this feature on Microsoft Research.

  4. The WPF and Silverlight designers mostly work.

    Now this shouldn’t be a point to make me smile or get excited about, but it is. The pain and suffering around the Visual Studio support for WPF and Silverlight designers has been so bad that a mostly-working, and sometimes truly innovative design-time experience within Visual Studio gives me real hope for these technologies. I’m actually excited about them now.

  5. Support for the MVVM pattern across both WPF and Silverlight.

    Speaking of that XAML stuff, if you write WPF or Silverlight code and don’t know MVVM, stop reading this article and learn about it here. I’ll wait. Ok, now you too should be excited to hear that there is improved support for MVVM across Silverlight and WPF in a unified way. Smiles baby!

  6. WF (Windows Workflow Foundation) has an AsyncCodeActivity class.

    While WF has traditionally supported both synchronous (activities that execute immediately) and asynchronous activities (for long running senarios where the workflow becomes idle and is unloaded from memory [click here for more details]), there has been an unserved middle ground. If you want to use threading in your activity and allow the workflow to go idle without it being unloaded from memory you were basically out of luck. This is the problem solved by the AsyncCodeActivity. WF 4 now has a class which has a BeginExecute / EndExecute pair of methods which much more closely models the regular .NET async design patterns.

  7. WF has a rehostable designer (really, they mean it this time).

    There are some great uses for giving regular users a WF designer experience with the right granularity of activities. Now it’s much easier. Here’s an app that rehosts the designer:



  8.  Configuration-free WCF Hosting.

    Hosting WCF services is now like hosting ASMX web services if you like the defaults. Just throw out a service + contract + address and it’s up and running. That’ll save a bunch of <system.serviceModel> configuration goo. Smiles!

  9. No more *.svc in our RESTful urls in IIS.

    With the ASP.NET routing framework and WCF REST introduced in .NET 3.5, we can create beautiful, expressive Uri’s for our websites. For example:

       http://lookatthiswith.me/watch/intro

    But this falls apart with WCF REST when we host it in IIS. Our service Uri’s look like this:

       http://lookatthiswith.me/services/lookieservice.svc/lookup/json/cf7

    And now we have this ugly .svc part-way through our Uri! Ick. Well, in .NET 4 that Uri is much more customizable and the .svc is gone. Smiles!

  10. ASP.NET MVC has wicked JavaScript support.

    JQuery is there by default. That’s awesome. But there is also a class similar to the Html class (for HTML helpers) called Ajax. This static class has functions like Ajax.ActionLink and effectively brings the functionality of UpdatePanel to MVC!

Well there you have it. 10 awesome things in .NET 4 that made me smile this week. I hope you find some to be welcome additions yourself! If you want to learn more about .NET 4.0, check out our recorded webcasts here: http://www.develop.com/dotnet4webcasts. Also have a look at my article from last month Six Things That’ll Surprise You About .NET 4.0. Finally, if you have some training funds laying around, I’d love to spend a week talking about these ideas with you in our What’s New in .NET 4.0 What’s New in .NET 4.0 class.

Michael Kennedy is an instructor for DevelopMentor where he specializes in core .NET technologies as well as agile and TDD development methodologies. Keep up with Michael via his Web site and blog at http://www.michaelckennedy.net or on Twitter: @mkennedy.


Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

ASP.NET WebForms + Routing Video and Downloads

Wednesday, December 09, 2009 11:38:45 AM (Pacific Standard Time, UTC-08:00)

I recently did a webcast for DevelopMentor on using the routing framework introduced in ASP.NET MVC within ASP.NET WebForms based applications to build more modern websites without a major rewrite of existing web applications. The talk was called "Building Modern Websites with ASP.NET WebForms".

Here's all the related downloads. We had some microphone troubles so I want to apologize in advance for the sub-optimal sound quality.

    Watch streaming video (WMV HQ)

   Watch streaming video (WMV HQ)    Download WMV Video Listen to MP3 Streaming Download MP3

You can also download the slides and peepleocity.com sample website built during the presentation.

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Six Things That’ll Surprise You About .NET 4.0

Wednesday, November 11, 2009 4:23:00 PM (Pacific Standard Time, UTC-08:00)

I recently wrote an article for DevelopMentor’s Developments entitled

   “Six Things That’ll Surprise You About .NET 4.0

You can read the entire article (republished just below this introduction) or if you’d rather see it as a quick set of 6 sides, you can see those here:

      6-Surprises-Slides


Six Things That’ll Surprise You About .NET 4.0
 
In this article, we will explore some of the new features of the .NET 4.0 as well as Visual Studio 2010. Some of these features are well-known, but others haven't gotten the press that they deserve. I've combed through .NET 4 to pull out the cool features that maybe didn’t get all the press – but should have. Read on and be pleasantly surprised!

[Note: Everything discussed below is based on .NET 4.0 and VS 2010 Beta 2]

#1 Visual Studio 2010                                                

You may have already known...

code-oriented features are a major focus of the improvements for VS 2010. For example, one style of development where developers sketch out a scenario in code involving a set of classes before they are completely written was painful in VS 2008 (e.g. TDD).

In this style of working, intellisense did all it could to get in your way and the IDE offered little to help move you forward. This gap was filled by 3rd party tools, most notably Resharper (http://www.jetbrains.com/resharper/).

In VS 2010, this capability will be built into the IDE -- can you say "CTRL-." anyone? See the sequence below for details.


        (click image for full size view)

But did you know...

that VS 2010 was rewritten in WPF and as part of that rewrite now has true multi-monitor support?

Yes, previously you could drag a build output window to a second monitor or the properties window to the side. But the part you really needed to split up, the code and designers, were solidly grounded in the one IDE window.

Not in 2010, you can pull these free and put them on your second, or third monitors. This aids both when working on UIs (you can see the designer and code-behind) as well as when doing TDD (you can see the test code and production code side-by-side).


             (click image for full size view)
 
#2 ASP.NET                                                             

You may have already known...

ASP.NET MVC is now integrated into VS 2010 and ships as part of .NET 4.0. In case you haven't heard of it, ASP.NET MVC is an alternative to the WebForms model that has been the backbone of ASP.NET for so many years. You can build well-factored, testable, and clean web applications more easily in MVC.

But did you know...

for the very first time a true open source project will become and integral and supported part of Visual Studio and .NET? JQuery will now be part of all web projects created by VS 2010 by default. That goes for ASP.NET WebForms, not just MVC projects. In fact, you can even open a support ticket with Microsoft concerning JQuery. You can read Scott Guthrie's original announcement for more details here.

  

#3 WF 4.0                                                        

You may have already known...

that Windows Workflow 4 has been completely rewritten for .NET 4.0. It's not even backwards compatible with .NET 3.5's version of WF. Basically WF 3 was a good try, but suffered from a couple of major problems that could not be overcome by simply refactoring the library.

But did you know...

WF 4 has a nice GUI workflow building designer that is part of the VS 2010 tools and moreover that designer is rehostable in your own Windows Forms or WPF applications.

Why might you do this? Consider an application where there is a scriptable aspect that is for non-developer types of users. Instead of giving them a scripting language such as Python, you can build WF activities and provide them with the designer to wire them together. This would give your application essentially a visual programmability.

  
                      (click image for full size view)

#4  Base-class Libraries                                      

You may have already known...

.NET 4.0 has threading constructs like Parallel.For which are designed for leveraging parallelism and multi-core hardware in CPU-bound situations. These are a perfect compliment to things like the ThreadPool class which are intended for parallelism when latency in external systems (databases, web services, file IO, etc) is the bottleneck.

But did you know...

there will be a new collection namespace called System.Collections.Concurrent?

Here you will find lock-free, thread-safe collections such as ConcurrentQueue. As we move from single core systems, to multi-core systems, and then into many-core systems (say 64 cores) these types of lock free objects will become increasingly important.



#5 WPF                                                          

You may have already known...

that the WPF and Silverlight designers in VS 2010 are greatly improved. You now have some features available that were only available in Expression Blend previously (e.g. data-binding).

    
        (click image for full size view)

But did you know...

the text rendering stack in WPF 4 has been completely rewritten.

Now text looks as clear in WPF as it does in GDI+ with ClearType enabled. This includes a host of edge cases, such as when the text is re-rendered via a VisualBrush, is used in animations, or even 3D text. Once again Scott Guthrie comes through with a great WPF 4 writeup on his blog.

    

#6 CLR and Base-class Libraries                         

You may have already known...

that .NET 4 ships with an entirely new runtime. There have been a number releases of .NET lately (2.0, 3.0, 3.5, 3.5 SP1) but all of these versions of .NET have run on the 2.0 runtime. For the first time since 2005, .NET 4 we'll have a completely updated runtime with new GC modes, side-by-side in-process execution of the 2.0 and 4.0 runtime, the loosening of COM interop rules with the No PIA feature (no Primary Interop Assemblies required).

But did you know...

there are new numerical types including BigInteger which supports arbitrarily big integers and ComplexNumber for modeling systems with advanced mathematical formulas which involve the complex number system.

    

You'll have to look around a bit to find these types however as they are not referenced by default. They are in the new System.Numerics library.

Summary                         

.NET 4 is going to be an exciting release with a some very polished libraries and tools. This article just touched on a few of them. 

  1. Visual Studio 2010 Multi-monitor Support
  2. JQuery is now part of ASP.NET
  3. WF 4 Has a Rehostable Designer
  4. BCL has New Thread-Safe Collections
  5. WPF has Real Text Support
  6. CLR and BCL has new Numerical Types


Michael Kennedy is an instructor for DevelopMentor where he specializes in core .NET technologies as well as agile and TDD development methodologies. Keep up with Michael via his Web site and blog at http://www.michaelckennedy.net or on Twitter: @mkennedy.
 
 
Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Webcast: Building Modern Apps in ASP.NET WebForms

Thursday, November 05, 2009 8:20:00 PM (Pacific Standard Time, UTC-08:00)

At DevelopMentor we have been running a bunch of free webcasts. Last month it was TDD and Agile. This month we are running 4 webcasts celebrating the announcements around .NET 4.0, Visual Studio 2010, and PDC 2009.

Join me Monday, November 23rd and register here:

     http://bit.ly/aspwebforms

We’ll talk about integrating ASP.NET’s routing infrastructure into existing an ASP.NET WebForms application. This allows you to build SEO websites with URLs like

      http://dotnet.ubbuzz.com/tag/.NET+4.0

while still taking advantage of all the productivity features of WebForms such as post-backs, controls, UpdatePanel, and so on.

We have room for a couple hundred more attendees so please register and be part of the fun. I promise lots of demos and somedisdainful comments about PowerPoint!

Share it with your friends (social, virtual, real, and other types) using the widgets below!

ASP.NET MVC: What’s that, you’d rather hear about ASP.NET MVC, not this creaky old WebForms stuff? That’s Brock Allen’s talk: http://bit.ly/intromvc

WF 4: Is WF 4 and visual programming your thing? Check out Maurice de Beijer’s WF 4 talk: http://bit.ly/meetwf4

New Parallel Extensions your thing: Check out Andy Clymer’s PFX talk. (link to follow soon).

Cheers,
Michael

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

TDD Space Invaders Video and Downloads

Wednesday, November 04, 2009 11:17:00 PM (Pacific Standard Time, UTC-08:00)

Recently Llewellyn Falco and I did a webcast for DevelopMentor where we demonstrated some TDD techniques and introduced Approval Tests. We let the audience choose our project and they chose Space Invaders. It was all great fun. Now the videos and MP3 streams are online and available for download.

Watch streaming video (WMV HQ)
Watch streaming video (WMV HQ)   Download WMV Video Listen to MP3 Streaming Download MP3

Be sure to check out the write-up we did afterward where we talked about the tools and gave you a chance to try it for yourself:

   TDD Space Invaders Write-up

You can also watch two other, higher level agile webcasts by Bill Nazzaro here:

   Agile Webcasts at DevelopMentor

Cheers!
Michael

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

TDD Invades Space Invaders

Wednesday, October 28, 2009 1:13:21 PM (Pacific Standard Time, UTC-08:00)
A joint post by Llewellyn Falco and Michael Kennedy

[Update: Get the videos and additional downloads for this webcast.]

As a follow-up to our "Avoiding 5 Common Pitfalls in Unit Testing" article we did a webcast where we took a problem from the audience and solved it live and unrehearsed on stage. These kinds of performances are always a risk but that's part of what makes them fun.

Of course, the question is could we have done it better? Here's your chance to try it for yourself (details below).

The Problem:

Our viewers chose to have us build the game Space Invaders. The first thing we had to do to sketch out a basic scenario we could implement. We started with a picture to remind what Space Invaders even was:



This was too big of a scenario for us to tackle in the allotted 40 minutes for programming. So then we started by creating a simpler scenario which we sketched out on the "whiteboard":


               Click for full size image.


Flushing Out the Scenario
:
In doing this, a couple of things were revealed about the game.

First, we wanted to make the tank and aliens all be the same size so we could put them on a grid. But then we saw that our bullet wouldn't fit that story, so we introduced the idea of relative sizes. We also realized that even though we drew the block, it was too complex for the first scenario and it would have to wait.

Notice that as we started writing the scenario in English, there are mistakes, irrelevancies, and problems with the order. This is OK. The thing to remember is that all of this was done for the sole purpose of creating a recipe for a scenario we could test. That scenario is the following:
[TestMethod]
public void TestSimpleKill()
{
   // 1. Create a 15x10 board.
   // 2. Place a 3x2 tank at 1x8.
   // 3. Place a 2x2 alien at 7x3 heading west.
   // 4. tank shoots
   // 5. advance 4 turns
   // 6. not won
   // 7. advance
   // 8. win
}

Now that we had the recipe, we could go about writing the code.

Here's your chance to play at home!

  1. Set your timer to 40 minutes.
  2. Create a new test project.
  3. Paste that method above.
  4. Translate the comments into code.
If you believe there's a better process, we invite you to try that as well.

We made it to step 4 during our presentation (download code below) and estimate another 15 minutes would have had the whole scenario done, tested, and well-factored.

Stories vs. Requirements (stories win):

We'd like to point out a couple of things about the story. First, it was quick to write the story. We did it in 5 minutes. Second, it translates well to code because it has behavior and objects working together. Let's compare that to the requirements that this story flushed-out.
  • Need a board
  • Boards should have width & height
  • Boards contain game objects
  • Game objects have a witdth, height
  • Game objects have the ability to move each turn
  • Aliens move either left or right each turn
  • Bullets move either up or down each turn
  • Bullets are 1x1
  • Tanks are 3x2
  • Aliens are 2x2
  • The game is not won until all the aliens are killed
  • The game is won if alll the aliens are killed
  • An Alien is killed if it is hit by a bullet
  • Tanks can fire
  • Firing with a tank creates a bullet going up from the space directly above the tank

Now we want to point out that this requirements doc is much hard to understand than our story. For example, if you were to add more requirements (e.g. an alien also shoots) is that easy to determine whether we have complete requirements? It also takes much more effort to create and especially to tell if it is complete. People aren't made to handle requirement documents well but we are story-telling machines. We embrace this in our coding techniques.

We'd also like to mention some of the tools discussed at the end.

For remote collaboration we use:

Skype (audio / video)
VNC for screen keyboard sharing
RDP (windows remote desktop) -- requires Windows 2003/2008 server for pairing.

Source Control:
TortoiseSVN
TortoiseGit

Developer Tools:
Resharper
CodeRush

Testing Tools:
MsTest (in Visual Studio Professional and up)
NUnit
NCover
TortioseDiff
Approvals Tests
Approvals Tests CodeRush add-in
Rhino Mock
TypeMock

If you try this scenario yourself, please leave a comment about your experience.

Download the code and slides from the webcast here:

   Code: TddWithLlewellynAndMichael.zip
   Slides dmtdd.pdf

Cheers -- Michael and Llewellyn

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Attend My Live, Free TDD Webinar with Llewellyn Falco and Myself at 10am Tomorrow!

Monday, October 26, 2009 3:29:46 PM (Pacific Standard Time, UTC-08:00)

[Update: See the follow-up post here: TDD Invades Space Invaders]

Tuesday, October 27, 2009 at 10am Pacific time Llewellyn Falco and I will be giving a live, unscripted, and no safety-net demonstration of Test Driven Development (TDD) as part of the DevelopMentor webinar series (this particular series is a 3-part series on Agile development).

We already have a bunch of attendees registered. But we have room for as many of you who are interested in agile and TDD. Sign up here:

   http://bit.ly/dm-tdd-m-and-l

In addition to core TDD techniques, you will see how an amazing technique and set of tools designed by Llewellyn called Approval Tests makes writing tests as simple as verifying an image or text file. Tired of writing 50 lines of test code for every 50 lines of production code but you still want the power of TDD? You need to learn more about Approvals and we'll demo that live tomorrow!

I hope to see you all online. Feel free to help me get the word out by tweeting this or shouting it (see icons below).

Cheers, Michael.

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Article: Avoiding 5 Common Pitfalls in Unit Testing

Friday, August 07, 2009 4:40:13 PM (Pacific Standard Time, UTC-08:00)
Llewellyn Falco and I recently wrote an article for DevelopMentor's Developments newsletter entitled Avoiding 5 Common Pitfalls in Unit Testing.

You can read it at the DevelopMentor website:

   http://www.develop.com/testingpitfalls

I've republished here for my readers. Enjoy!

[Update: We have also done a webcast demonstrating some of these ideas, which we wrote up here:
http://www.michaelckennedy.net/blog/2009/10/28/TDDInvadesSpaceInvaders.aspx]

Avoiding 5 Common Pitfalls in Unit Testing

by Llewellyn Falco and Michael Kennedy

When I started out with unit tests, I was enthralled with the promise of ease and security that they would bring to my projects. In practice, however, the theory of sustainable software through unit tests started to break down. This difficulty continued to build up, until I finally threw my head back in anger and declared that

"Unit Tests have become more trouble than they are worth."

So we stopped. Not all once, but over the months our unit tests died a quiet death. When tests would stop working, we just ignored them. When new features were reported, they were developed without unit testing. At first, it seemed great. We were able to move without the baggage of maintaining the old tests! But soon all the original problems of having a system without tests came back to us. Things keep breaking, deadlines were increasingly pushed back. Releases came with an extraordinary amount of stress, late nights & weekends. The final straw came when we were forced to rush out an immediate update, and ended up taking down the company for 2 days straight. Our new motto became:

"Unit Testing: you're damned if you do, you're damned if you don't."

In the end, we decided that despite the hardship caused by maintaining unit tests, it just wasn't feasible to operate without them. So we started down the road to re-incorporate testing into our software development process. As the months went by, however, we discovered that the hardships we remembered had not returned. Looking back, we realized that we had made many mistakes the first time around. The second time around we were smarter. So you, too, can enjoy the benefits of unit tests here are the 5 major pitfalls we encountered the first time around, and how you can avoid them.

Pitfall #1: Tests are hard to maintain.

Because tests were only there to service and support the production code, they became second class citizens. We would spend time carefully choosing method names, refactoring our code to keep our classes and methods small, and so on. But we never applied these same principles to our test code.

As a side-effect of adding back the old tests, we reviewed and cleaned them up with the same level of scrutiny we gave to our "real" code. Suddenly the tests were easier to maintain. While this should not be a surprise to anyone, it wasn't util this moment that we realized why they had been so hard to maintain in the first place:

Our tests were hard to maintain because we weren't maintaining them.

Solution: Going forward, we expect the same quality of code (or higher) in the unit tests as we do for our production code. That means
  • We remove duplication
  • We carefully consider method names
  • We create convenience functions for testing features
  • We keep our methods short
  • We code-review our unit tests

Pitfall #2: Tests are lot of work to write.

We found that in order to test even simple things we would have to write lots of code to setup and execute the scenario. Even something simple like "create a new user, and receive welcome email" would turn into 40-50 lines of step by step instructions.

Not only was this a pain to write the 1st time, it became a nightmare to maintain. Little changes would mean re-reading those functions to detect if the test was failing because we broke something, or simply because we had changed something. Once that was discovered, we would then have to update the now out of sync test code.

The solution we actually found may surprise you. We found that writing out our tests in English and then translating each line into 1 line of code naturally created the appropriate levels of abstraction and readability.

For example, let's consider testing the following scenario:

Who are you receiving the most email from?
  1. Create you - the user
  2. Mike sends you 3 emails
  3. Mary sends you 4 emails
  4. Joan sends you 2 emails
  5. Verify your greatest "emailer" is Mary
This will naturally lead us to write the following test method and helper method:

[TestFixture]
public class AccountTests
{
    private MockMailServer mockMailServer = new MockMailServer();

    [Test]
    public void WhoAreYouReceivingTheMostEmailFrom()
    {
        User you = User.CreateNew( "you" );
        User mike = SendEmailHelper( CreateUser( "mike" ), you, 3 );
        User mary = SendEmailHelper( CreateUser( "mary" ), you, 4 );
        User joan = SendEmailHelper( CreateUser( "joan" ), you, 2 );

        Assert.AreEqual( mary, you.GetGreatestEmailer() );
    }

    private User SendEmailHelper(User from, User to, int quantity)
    {
        for ( int i = 0; i < quantity; i++ )
        {
            EMail mail = new EMail()
            {
                To = to, 
                From = from, 
                Body = "Sample",
                Subject = "test"
            };

            mail.SetFormat( Formats.Html );
            mockMailServer.Send( mail );
        }
        return from;
     }

Notice that to a programmer, the lines of code in the WhoAreYouReceivingTheMostEmailFrom test are as easy to read as the lines of English were. We were naturally motivated to create the "SendEmailHelper" function because that was required by one-to-one correlation between the lines of English and the lines of test code. However, without that helper, our test would have become an unreadable rat's nest. This also naturally removes some duplication, increases maintainability, and allows for some reuse of the test convenience functions. This won't be the only test that requires us to send email; for example, we may want to test that we can find out to whom you sent the most email.

Let's compare this to how our tests would look if we had just hacked out the scenario:

[Test]
  public void WhoAreYouReceivingTheMostEmailFrom()
  {
      User you = User.CreateNew("you");
      User mike = CreateUser("mike");
      for (int i = 0; i < 3; i++)
      {
          EMail mail = new EMail{To = you,From = mike, Body = "Sample", Subject = "test"};
          mail.SetFormat(Formats.Html);
          mockMailServer.Send(mail);
      }
      
      User mary = CreateUser("mary");
      for (int i = 0; i < 4; i++)
      {
          EMail mail1 = new EMail{To = you,From = mary,Body = "Sample",Subject = "test"};
          mail1.SetFormat(Formats.Html);
          mockMailServer.Send(mail1);
      }
          
      User joan = CreateUser("joan");
      for (int i = 0; i < 6; i++)
      {
          EMail mail2 = new EMail {To = you, From = joan,Body = "Sample",Subject = "test"};
          mail2.SetFormat(Formats.Html);
          mockMailServer.Send(mail2);
      }
      
      Assert.AreEqual(mary, you.GetGreatestEmailer());
      }

Because we wrote the first version in English it's also easier to detect a mistake. You may have noticed that the second example had a typo at line 31, making Joan the biggest emailer. In general long methods have the disadvantage of obscuring intent. Unfortunately the 'follow a script' aspect of testing lends itself to writing long methods. By writing the tests in English and then doing a 1-to-1 conversion to code we can counter this vulnerability.

Write the tests in English before you code them.

Pitfall #3: Adding a new feature breaks a lot of tests that I then need to adjust.

I always dreaded adding new features because I knew it meant the existing tests were going to complain about the changes. It seemed like the tests themselves were resisting change to my system, rather than supporting it. As I made changes and the tests broke, I was always trying to figure out if those changes were "expected" because of the new feature, or unintended bugs I had introduced into my software.

Nowadays, we always prep the system for the new feature. This allows us to isolate 'expected' changes from unintended bugs. Furthermore, once we have finished prepping for the new feature, we find it extremely easy to actually add that new feature. Best of all, if the unit test breaks now, we know it's because of unexpected side effects of our changes.

This 'prepping' period falls under the title of 'refactoring' and requires the simple rule that during this stage you do not change the behavior, only the implementation. This sounds straight forward and simple, but in practice it requires a great deal of discipline.

Personally, I still find it a challenge to NOT fix a bug discovered during refactoring. I have to force myself to leave it alone and wait until I have finished refactoring before changing (Fixing) this behavior, but this discpline has paid off many, many times.

During this period, the support provided by your unit test suite really shines. Those tests allow me to rework my code with confidence. Afterwards the architecture in place has been custom designed to support the addition of this particular new feature, thus making its implementation quite straightforward. In our experience the 'prepping' work tends to actually take more time than we spend adding the actual feature itself, but the total time to implement is much less.

By spliting the work into two phases, we can emphasize the fact that the unit tests are supporting the existing system allowing its architecture to evolve so that extending it does not become increasingly difficult.

Before I would ask myself "How can I add this new feature?" Now I ask "How can I make it so this new feature will be easy to add?"

Prep the system for the new feature first.

Pitfall #4: When I change something a whole bunch of tests break even though I haven't broken the system.

There are many ways to solve the same problem. In the past, we tended to test a specific implementation of a solution instead of testing that we had a solution. Because we were focused on the specifics of implementation, changes to our solutions kept breaking our tests, even though we still had a valid solution. Moreover, because the tests were closely tied to implementation, rediscovering the intent and separating it in the tests became cumbersome. As we became more proficient at writing tests in English, we were able to create unit tests that described the expected behavior. This conveys a higher level of intent, and made the tests much less brittle.

Let's look at an example:
[Test]
  public void TestGatewayCallSuccessful()
  {
      var gateway = new Gateway {Mask = "ExampleCode.*"};
      var enviroment = new Dictionary();
      enviroment.Add("path", "ExampleCode.HelloWorld");
      string result = gateway.ExecuteRequest(enviroment);
      Assert.IsTrue(result.Contains("Hello World"));
  }
  
  [Test]
  public void TestGatewayBlocksInvalidMasks()
  {
      Assert.IsFalse(Gateway.IsValidForMask(
          "Example.*", "ExampleCode.HelloWorld"));
          
      Assert.IsFalse(Gateway.IsValidForMask(
              "ExampleCode.*.Extras.*", "ExampleCode.HelloWorld"));
              
      Assert.IsTrue(Gateway.IsValidForMask(
              "ExampleCode.*", "ExampleCode.HelloWorld"));
  }


In this example, we wrote our second test TestGatewayBlocksInvalidMasks so we could easily test a few examples to make sure our implementation was correct. In doing so we exposed a method IsValidForMask, which was an implementation detail and was only made public in order to make testing easy and intentional. We did this because actually executing something to get the failure was much more involved as evidenced by the first test (TestGatewayCallSuccessful).

Let's take a look at the specific solution we've come up with:

public class Gateway : IRunner
  {
      public string Mask { get; set; }
      
      public String ExecuteRequest(Dictionary environment)
      {
          string path = environment["path"];
          AssertValidClass(path);
          IRunner instance = 
                (IRunner)Activator.CreateInstance(Type.GetType(path));
          
          return instance.ExecuteRequest(environment);
       }
       
       private void AssertValidClass(string path)
       {
          if (!IsValidForMask(Mask, path))
          {
              throw new Exception(String.Format(
                    "Invalid Path '{0}' for Mask '{1}'", path, Mask));
          }
       }
       
       internal static bool IsValidForMask(String mask, String path)
       {
           mask = mask.Replace(".", "\\.").Replace("*", ".*");
           Regex regex = new Regex(mask);
           
           return regex.IsMatch(path);
       }
 }

As we can see, even though we are only creating this gateway once each time a call to ExecuteRequest is made we have to recreate the regex expression (line 31 & 32). It would be nice to do this just once. Let's take a look at a more efficient solution:

public class Gateway : IRunner
  {
      private string mask;
      private Regex regex;
      
      public string Mask
      {
         get { return mask; }
         set
         {
            mask = value;
            regex = new Regex( mask.Replace( ".", "\\." ).Replace( "*", ".*" ) );
         }
      }
      
      public String ExecuteRequest(Dictionary environment)
      {
           string path = environment["path"];
           AssertValidClass(path);
           IRunner instance = (IRunner) Activator.CreateInstance(Type.GetType(path));
           
           return instance.ExecuteRequest(environment);
       }
       
       private void AssertValidClass(string path)
       {
           if (!regex.IsMatch(path))
           {
               throw new Exception(String.Format("Invalid Path '{0}' for Mask '{1}'", path, Mask));
           }
       }
 }


Unfortunately this refactoring breaks the first set of tests. Notice that the function we are calling no longer even exists. However, let's look at what happens if we write our tests for the behavior rather than the implementation:

[TestFixture]
  public class GatewayBehaviorTests
  {
     [Test]
     private void TestGatewayCallSuccessful()
     {
         string result = Run("ExampleCode.*", "ExampleCode.HelloWorld");
         Assert.IsTrue(result.Contains("Hello World"));
      }
      
      [Test]
      public void TestGatewayBlocksInvalidMasks()
      {
          AssertValidForMask(false, "Example.*", "ExampleCode.HelloWorld");
          AssertValidForMask(false, "ExampleCode.*.Extras.*", "ExampleCode.HelloWorld");
          AssertValidForMask(true, "ExampleCode.*", "ExampleCode.HelloWorld");
      }
      
      private static String Run(string mask, string path)
      {
          var gateway = new OptimizedGateway {Mask = mask};
          var enviroment = new Dictionary();
          enviroment.Add("path", path);
          string result = gateway.ExecuteRequest(enviroment);
          return result;
      }
      
      private void AssertValidForMask(
      bool exceptionExpected, string mask, string path)
      {
          Exception found = null;
          try
          {
             Run(mask, path);
          }
          catch (Exception ex)
          {
             found = ex;
          }
          Assert.AreEqual(exceptionExpected, found == null);
       }
}

There are a few things to notice now:
  • This test not only works for the new code, but the old code as well. This is because the behavior has not changed, just the implementation.
  • We have not sacrificed readability or clarity of intent. In fact the first test TestGatewayCallSuccessful has actually gained readability.
  • There is the introduction of helper methods in the unit test. We find that this is a side effect of writing tests for readability and intention.
In the end, we realized there is a particular code smell for this problem.

If a different implementation of a solution requires different tests, you are testing to the wrong level.

Pitfall #5: There are just too many possibilities to test

When we first began unit testing, we felt that we had to test as many inputs as possible because we believed the purpose of the unit tests was to ensure complete quality of our code. What we have learned is that the world is not black and white, and neither is testing. It is not the case that we either have verified code or unverified code. There are levels of protection. In fact there is a level at which you get diminishing returns from new inputs and, surprisingly, that number is often very small.

For example: Imagine the following scenarios :

Scenario 1
You have a method
public int doSomething(int a, int b) {/*...*/})
Does this method work?
Will it blow up if I run it?
On a scale of 1-10 what is your confidence level?
Confidence Level 2: In our case, our confidence started out at 2. All we know is that it compiled. Any number of things could be wrong..
Scenario 2
Now, assume you have an invocation of the method
doSomething(2,3);
When you run this, it does not crash although you have no way to check its result.
What's your confidence level now?
Confidence Level 6:  As soon as it's been executed, our confidence jumps up to a 6. We know that most bugs come from incorrect wiring, or null pointers, and so on. Now we know it's not blowing up, but still don't really know that it's working
Scenario 3
Now imagine that you have a test
assertEquals(8, doSomething(2,3));
This test passes.
What's your confidence level now?
Confidence Level 8:  Just a single confirmation pulls us all the way up to a confidence level of 8. Notice that we are still just at 1 test case. A few more and we'll be in the 9's, but how many more cases would you need to say with absolute confidence that this works? (hint: 2^32 * 2^32).
     
Tests are like seatbelts: just because they won't guarantee your survival in all crashes, it doesn't mean you shouldn't wear them. Take the extreme case of a motorcycle helmet. You are only protecting a small part of your body, but you are significantly improving the odds of survival if something goes wrong.

A general rule of thumb for the number of cases to tests is "3 is a big number".
  1. Test the happy path
  2. Test an edge case
  3. Test an error case, if you have one
Start with the happy path. If you still are worried, try an edge case. Wait until a problem presents itself before you test further.

Spend your time where it counts.


Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Article: Building a Twitter Application in .NET

Friday, August 07, 2009 12:22:02 PM (Pacific Standard Time, UTC-08:00)

I recently wrote an article for DevelopMentor's Developments newsletter entitled Building a Twitter Application in .NET.

You can read it at the DevelopMentor website:

   http://www.develop.com/twitternetapps

I've republished here for my readers. Enjoy!


Building a Twitter Application in .NET

by Michael Kennedy (@mkennedy)
http://www.michaelckennedy.net

Twitter has become one of the web's hottest properties. It is a central part of mainstream news programs such as CNN's Anderson Cooper 360, congressional debates, and talk shows. In fact, it grew at a rate of 1400% this past year [bit.ly/jG9BG].

If your company wants to interact with your customers in a modern and engaging experience, you need to be on Twitter. In fact, if you have customers that really like or dislike you, they are probably talking about you on Twitter. You should be part of that conversation.

In this article, we will explore how to build a rich interactive experience on Twitter that goes beyond just creating a new Twitter account. We will build a .NET application that uses the Twitter API (a free service) alongside other cool technologies such as the WCF REST Starter Kit [http://bit.ly/v8mBb] and LINQ to fully leverage the Twitter experience.

Whether you want to build a community around your brand or you want to build the next real-time, social community website like .NET Developer Buzz [http://dotnet.ubbuzz.com/], this article will cover the technologies required to get the job done.

If you want to download the sample application to follow along, you can get it here:
   http://www.michaelckennedy.com/Samples/SampleStatusUpdater.zip

While you're at it, be sure to follow DevelopMentor on Twitter:
    http://twitter.com/dm_the_company

Let's Start Small

I will show you how to fully leverage the Twitter API, but many tasks can be accomplished using simpler tools and you may be better starting there. Let's look at a few things that we can do without the Twitter API.

Case 1. You want to display your latest Twitter messages on your website.

Your tweets[1], as they're called, can be consumed as a simple RSS feed. So you may want to simply pull this feed into your website rather than digging into the Twitter API and consuming custom XML or JSON formats. An example of consuming Twitter in this fashion can be found on my website's front page [http://www.michaelckennedy.net/].

To get your RSS feed, just visit your profile page and get the RSS tweet link, e.g. "RSS feed of mkennedy's tweets" [http://bit.ly/guhZU]

[1] Tweet - these are what the individual messages sent on Twitter are called. If the name sounds weird, I'm sure you'll get used to it. Remember that there was a time when Google was just a noun.

Case 2. You want to watch and manage multiple accounts at the same time.

Most Twitter clients only support a single user. But there are a couple of good tools that allow you to manage multiple accounts. My current favorite is one called bDule and you can get for free at http://www.sobees.com/bdule.

Beyond the Small

There are times when you want to do more than simply syndicate your Twitter stream. Let me give you an example. At DevelopMentor, we have had many instructors on Twitter talking about their own interests. But we didn't have a corporate Twitter presence. We decided to create our corporate presence by pulling all our instructors individual tweets and rebroadcasting them from our DevelopMentor Twitter account: @dm_the_company

We wanted to keep a sense of the original instructor who wrote the message, so we append on an attribution. For example:

"Software Transactional Memory is released! (via @mkennedy)

and we wanted to do this in a flexible way. In short, we needed more functionality than Twitter provides.

There are actually three services that do this sort of thing and they looked promising.

   http://www.connecttweet.com/
   http://www.grouptweet.com/
   http://cotweet.com/

But in the end, nothing completely matched our requirements. So we decided to write our own application to publish everyone's tweets under the DevelopMentor banner. There are few simple steps involved as well as a lot of details we won't go into yet.

  1.  Take a list of Twitter accounts and download everyone's statuses.
  2. Determine which messages we haven't seen before.
  3.  Publish these new statuses under our corporate account.

We can actually implement a simplistic version of this by continuing to use the public RSS feeds of the individual accounts in conjunction with a very handy Twitter API wrapper called TwitterooCore which you can find at http://rareedge.com/twitteroo/blog/.

The Twitter API

In practice, there is simply data missing from the RSS feed that we require as well as features missing from the Twitteroo Core that move us deeper into the Twitter API. One thing you may well miss is the ability to tie together conversations. For example if Bob says "hello" and Jerry says in reply "@bob Back at you!" Twitter tracks that Jerry replied to Bob and publishes this link in the stream. To get access to these types of features and many other optimizations, you'll need to use the REST-based Twitter API.

The Twitter API is documented at http://apiwiki.Twitter.com/

There you can do things like get the users tweets, if their tweets are public, by requesting:

http://twitter.com/statuses/user_timeline.xml?screen_name=mkennedy

What you get back to dependent on the requested format. Here we're asking for XML (user_timeline.xml) but we can also get JSON, RSS, or ATOM.

Similarly, we can update our status by making a POST request to:

http://twitter.com/statuses/update.xml

Here again we have the four possible formats: XML, JSON, RSS, ATOM. However this time we're using a form post for the request to update the user status which is then in-turn returned as XML.

Great, we have this cool REST API based on loosely-typed GETs and POSTs. Should we program against it using fundamental .NET types such as WebRequest, WebClient, and similar classes? We could. But WebRequest is so .NET 1.0 (circa 2001). There is a much newer API on the verge of release from Microsoft: The REST Starter Kit [http://bit.ly/1IF3Ji].

While this toolkit is generally geared towards building to RESTful WCF services, there's also a great set of classes for building REST clients. We will use these classes to write our application. Let's take a look at how we can use the Twitter API to write are simple application.

The REST Starter Kit

Part 1 - Getting the users of tweets.

We need to download the users messages as XML and convert them to .NET objects that we can consume our application. This is really straightforward because the REST Starter Kit as a cool feature to Visual Studio: "Paste XML as Types". This feature will take an XML file and auto-generate types based on the inferred XML schema. In our case, the XML file we will use is returned from the user timeline.

http://twitter.com/statuses/user_timeline.xml?screen_name=mkennedy

Open a link in a web browser, choose view source, and copy some XML. Then go to Visual Studio, choose edit, Paste XML as Types. Of course you must have the REST Starter Kit installed for this to work.[2]

[2] In my experience I ran into some errors deserializing the response from Twitter. See the The Real World Intrudes section at the end of the article if you run into difficulties.

After generating our status related types, we can use the HttpClient class to download the statuses.

Listing 1.

private static void GetStatuses(IEnumerable userNames)
{
    XmlSerializer serl = new XmlSerializer(typeof (statuses));
    serl.UnknownElement += delegate { };

    foreach (string name in userNames)
    {
        string url = string.Format(
            "http://twitter.com/statuses/user_timeline.xml?screen_name={0}",
            name);

        HttpClient client = new HttpClient(url);

        HttpResponseMessage response = client.Get();
        response.EnsureStatusIsSuccessful();

        string contents = response.Content.ReadAsString();
        Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(contents));
        statuses userStatuses = (statuses) serl.Deserialize(stream);

        if ( userStatuses.status.Length > 0 )
        {
            Console.WriteLine( "@{0}'s latest tweet: {1}", name,userStatuses.status[0].text );
        }
        Console.WriteLine();
    }
}

There are two main things happening in this code. We're using the HttpClient class to download the web content associated with the given user's timeline. Then we're using the XmlSerializer in conjunction with the auto-generated XML-serializable types from the "Paste XML as Types" command. That's all there is to it. The REST Starter Kit does most of the work for us.

Part 2 - Checking for New Messages

Now that we have all the statuses, we need to find the ones that we haven't broadcasted from our main account and send them along to step 3. We won't go into detail on how to track that. But you can imagine a simple database that facilitates a LINQ to SQL query like this:

Listing 2.

public StatusUpdate[] FindRebroadcastableStatuses(StatusUpdate[] updates)
{
    return
        (from up in updates
         let neverPosted = up.User.LastPostBroadcasted == null
         let afterPostDate = up.Time > up.User.LastPostBroadcasted
         where neverPosted || afterPostDate
         select up).ToArray();
}

Part 3 - Publishing the Statuses

Now that we've gathered the statuses of our various users, it's time to rebroadcast them to our community. We're going back to the Twitter API to update our status. Again will use the HttpClient class and following the RESTful principle of using POST to add new items to a given URI. We will do an HTTP POST to our status to add a new message to the account.

Listing 3.

private void UpdateStatus(string newStatus, long? replyToId)
{
    string url = "https://twitter.com/statuses/update.xml";

    HttpClient client = new HttpClient( url );
    client.TransportSettings.Credentials = 
        new NetworkCredential( twitterUser, password );

    HttpUrlEncodedForm form = new HttpUrlEncodedForm();
    form.Add( "status", newStatus );
    if ( replyToId != null )
    {
        form.Add( "in_reply_to_status_id", replyToId.ToString() );
    }

    HttpContent content = form.CreateHttpContent();

    HttpResponseMessage message = client.Post( "", content );
    message.EnsureStatusIsSuccessful();
}

This time we create an HTML form using the HttpUrlEncodedForm class. We set the status field to our new status. If this status as a response to a previous tweet then we add the in_reply_to_status_id so Twitter knows to add a "in reply to..." tag to the tweet.

And there you have it. Working with the Twitter REST API is really quite straightforward. If you use the REST Starter Kit it's downright easy.

The Real World Intrudes

But wait a minute. This is reality and building bulletproof applications is never that simple. There are at least five significant gotchas you have to address in practice when working with Twitter and the REST Starter Kit.

1. There will be times when Twitter is unavailable. You have to be ready for crashes and other types of randomness.

Twitter is one of those sites that can barely handle the traffic it is receiving. With its 1400% growth, this isn't getting much better. So you must program defensively and assume that many of your API requests will fail.

2. The Twitter API is a free service. By default, you are limited to a small number of requests per hour. Many of the limits are around 150 API calls / hour. You may need to carefully design your application to work within the limits. Some applications simply need more data than this permits. For example, .NET Dev Buzz [http://dotnet.ubbuzz.com/] has to track thousands of users. In that case, you will have to get your application white listed with Twitter. You can do that here:

http://twitter.com/help/request_whitelisting

3. The date-time format used by the Twitter API is not directly parseable in .NET. The format returned is in the format "Fri Feb 01 18:18:08 +0000 2008". But if we change this to "Fri Feb 01 +0000 2008 18:18:08" it is parsable. So you might need to adjust these date-time values.

4. You will get 417 error codes when you try to talk to Twitter using the default configuration. The fix is not immediately apparent, but it is very simple. So if you see the following error:

System.ArgumentOutOfRangeException: ExpectationFailed (417) is not one of the following: OK (200), Created (201), Accepted (202), NonAuthoritativeInformation (203), NoContent (204), ResetContent (205), PartialContent (206) at Microsoft.Http.HttpMessageExtensions.EnsuRESTatusIs()

Just to set the following property: ServicePointManager.Expect100Continue = false;

5. "Paste XML as Types" doesn't entirely work. For some reason, certain messages from Twitter are not deserializable to the types generated with this command. My experience was that I didn't actually care about the data causing the problem. So I just removed that part of the generated type. You may have to subscribe to the XmlSerializer error events to prevent exceptions.

Conclusions

I hope you now have a greater appreciation for what you can do with Twitter and how it can help you build your brand or build engaging applications. We've used the REST Starter Kit to make it easy to consume the Twitter API. You've even seen some of the odd things that can go wrong and how to fix them. Don't forget to download the sample application here:

http://www.michaelckennedy.com/Samples/SampleStatusUpdater.zip

Now get out there and build something cool.

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Keep up with DevelopMentor on Twitter

Thursday, July 23, 2009 2:42:04 PM (Pacific Standard Time, UTC-08:00)

You may know that I work for DevelopMentor where I'm an instructor in the .NET curriculum (among other cool things I do there). You probably also know I'm kind of loopy for Twitter as evidenced by my Twitter page and .NET community site driven by Twitter:

   http://twitter.com/mkennedy
   http://dotnet.ubbuzz.com/

Today those two things came together in a big way. Introducing DevelopMentor's Twitter presence:

    @dm_the_company
   http://twitter.com/dm_the_company

I encourage you get out there and follow us! Here you will see all the combined Twitter messages of most of the DevelopMentor instructors as well as a couple of messages from DevelopMentor itself. You'll get the chance to keep on top of the world as viewed by some of the smartest people I've had the chance to work with: the DM instructors! You'll see which instructor posted any given message with an attribution at the end (either "via @marksm" or ^MS depending on the available space).

I'm excited about this not just because I think it is cool and useful (and has to do with Twitter :) ), but over the last few days I'm the guy who wrote the back-end systems to make this all go. It was a short but fun project. It's a real testament to .NET that this was mostly written an hour.

After you follow @dm_the_company you might want to interact with some of the instructors directly. Here's our Twitter accounts in a single place for your reference:

http://twitter.com/bmaso
http://twitter.com/danamiga
http://twitter.com/jason_diamond
http://twitter.com/jplane
http://twitter.com/markblomsma
http://twitter.com/marksm
http://twitter.com/mauricedb
http://twitter.com/mkennedy
http://twitter.com/nielsberglund
http://twitter.com/richardblewett
http://twitter.com/tonysneed
http://twitter.com/wallacekelly

I hope you enjoy the conversations we're bound to have on Twitter. Come be part of it.

Signed: @mkennedy

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

ASP.NET Routing in Windows Azure Using WebForms

Wednesday, May 27, 2009 1:53:18 PM (Pacific Standard Time, UTC-08:00)

I'm a huge fan of ASP.NET Routing. It gained popularity as the part of ASP.NET MVC which channels requests for a given URL to the right controller action. In a wise move, Microsoft moved the routing infrastructure out of ASP.NET MVC and into its own assembly with the release of .NET 3.5 SP1.

With ASP.NET Routing you can construct search engine optimized and human friendly URLs such as these:


Here part of the URL (tag or user) selects the page and part of the URL (everything or codinghorror) are effectively query parameters to the page.

This is well documented in the ASP.NET MVC world running on your server - you can't get anything done without it in MVC. But what about Windows Azure? What if you don't want ASP.NET MVC? What if you're a traditional type of person and want all the goodness that comes with what is now called ASP.NET WebForms (aka "normal ASP.NET")?

In this brief post, I'll cover how to use ASP.NET routing and ASP.NET WebForms in Azure. The sample project can be downloaded if you want to follow along. Phil Haack has written a good post on using routing alongside ASP.NET WebForms so I won't cover too much background information.


How does this change for Azure?

The short answer is that it doesn't. If you get routing working for IIS 7 in your web app, you can effectively deploy it to Azure. But the steps always felt convoluted to me when reading others' write-ups on this. So let's run through converting a Windows Azure Web Role (essentially a "stock" ASP.NET WebForms app) to use routing in Azure.

First you'll need the Azure SDK and Visual Studio tools:


  1. Next, create a new solution in Visual Studio by choosing Cloud Service->Web and Worker Cloud Service.

  2. Add a new Global.asax file to your web role project.

  3. Add a reference to System.Web.Routing and System.Web.Abstractions in your web role project.

  4. Define a custom class that derives from IRouteHandler which will map URL parameters into the HttpContext for use in your pages:
    internal class CustomRoute : IRouteHandler
    {
        public CustomRoute(string virtualPath)
        {
            VirtualPath = virtualPath;
        }
    
        public string VirtualPath { get; private set; }
    
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            foreach ( var aux in requestContext.RouteData.Values )
            {
                HttpContext.Current.Items[aux.Key] = aux.Value;
            }
    
            return BuildManager.CreateInstanceFromVirtualPath(
                       VirtualPath, typeof( Page ) ) as IHttpHandler;
        }
    }
    
  5. Register these routes in the Application_Start method of your Global.asax:
    protected void Application_Start(object sender, EventArgs e)
    {
        RouteTable.Routes.Add( "ShowName",
               new Route(
                "naming/show/{name}",
                new CustomRoute( "~/ShowName.aspx" )
                ) );
    
        RouteTable.Routes.Add( "CreateAccount",
               new Route(
                "account/begin",
                new CustomRoute( "~/Account.aspx" )
                ) );
    
        RouteTable.Routes.Add( "Home",
               new Route(
                "home",
                new CustomRoute( "~/Default.aspx" )
                ) );
    }
    
    Now if you run your app, you might expect the routing infrastructure to work. Inside the ASP.NET Dev Server (aka cassini) this will likely work. But in the Azure Development Fabric you'll see this:



    The problem is you need to tell IIS 7.5 to get out of the way and let the request get to ASP.NET.

  6. We'll define a class to short-circuit the IIS validation
    class Iis7RoutingHandler : UrlRoutingHandler
    {
        protected override void VerifyAndProcessRequest(
            IHttpHandler httpHandler, HttpContextBase httpContext)
        {
        }
    }
  7. Modify the web.config by adding a handler and module to the system.webServer section:
    
    
    ...
      
    
    
      
    
    
    
  8. Finally, we need to recover the data passed to the page. For example, in the sample project we have:

    route: /naming/show/{name}
    example: /naming/show/michael-kennedy

    How will our page access the value of name? Recall that our custom route stashes the values in HttpContext.Current.Items. We'll just pull them back out as follows in our Page_Load method of our ASPX class:
    LabelName.Text = (string)HttpContext.Current.Items["name"];
That's it! You can see our routes working in our WebForms app running in Azure (well, technically the screenshot is the dev fabric - but it works in the cloud as well):

Download the source and try it for yourself: AzureRoutingSample.zip (136 KB)

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Article: Azure Storage

Wednesday, April 08, 2009 12:03:23 PM (Pacific Standard Time, UTC-08:00)

I recently wrote an article for DevelopMentor's Developments newsletter entitled Azure Storage. Read it at the DevelopMentor website here:

http://www.develop.com/content/newsletters/aprilazure

I've republished here for my readers. Enjoy!


Developments: Azure Storage

by Michael Kennedy

[Listen to this article as a podcast: Azure-Storage-Article-Kennedy.mp3]

October 27th 2008, Los Angeles CA - It's 9 AM and Microsoft is hosting PDC (their most forward looking developer conference). Ray Ozzie and company are introducing Windows Azure: A new platform which is their first foray into the nascent world of large-scale utility computing. This scalable and reliable platform-as-a-service functionality is commonly referred to as "Cloud Computing" because it runs somewhere out there on the Internet.

Computing platforms that rival the reliability of the utility grids (e.g. electric and gas) which we daily take for granted have long been the stuff of dreams.

A few companies have realized this dream - Google and Amazon come to mind as a couple of the rare exceptions who have accomplished this goal. These companies' web properties seem to handle unbounded amounts of traffic with zero down time. The data centers, redundancies, software engineering and operations know-how required to make this happen are exceedingly expensive. Some reports have Google spending over $2.4 billion (that's 2,400 million dollars) on data centers in 2007 alone.

Prior to large-scale cloud computing efforts (circa 2005), most of us could only dream of such scalability and reliability. Today we have at least three highly reputable companies offering some kind of pay as you go cloud computing platform - Microsoft, Amazon, and Google.

Microsoft's Azure is a new comer to the industry. But for .NET developers, it is not to be ignored. Azure allows you to use your existing skills to build essentially the same .NET applications you are familiar with and "deploy them to the cloud."

These scalable, reliable, and geographically-replicated applications that run on Azure depend on data of course. Virtually all applications we write will be nothing without their underlying data. But if we simply use the tried and true methods of data storage such as the file system or a (single) database server our data is not all that scalable or reliable. Because we cannot have a scalable and reliable application without data, we need a new mechanism for storing and accessing data from our Azure applications.

Enter Azure Storage

Azure storage is the storage component of the Azure platform. It is actually three data services in one:

  • Blob Storage - stores unstructured data essentially as a file, limited to 50 GB of data per blob.
  • Table Storage - stores structured data that is somewhat like a database. For full database capabilities there is a high level feature called Sql Data Services (SDS).
  • Queues - provides interprocess communication functionality between various web and worker roles in your hosted services or even applications running outside of Azure. Queues can pass small xml or binary messages - less than 64 kb per message.

In this article, we will cover just the basics of the three storage services of Windows Azure. I want to give you a sense for what it's like to program against Azure Storage. At the base level all access to Azure Storage uses pure REST APIs. This means that you can access it from any HTTP enabled platform / language. For example, to download the blob data called "config.xml" in the container called "settings" for the Azure project "kennedy" you would simply issue a GET to the Uri:

   http://kennedy.blob.core.windows.net/settings/config.xml

To save data in a blob you do HTTP POSTs and PUTs in a similar fashion. However, real life is full of edge cases, error handling, security, and serialization which makes the pure HTTP model error prone. Thus, a sample library serves as the de facto .NET API to Azure Storage and ships with the Azure SDK. It is called StorageClient and can be found in default installs here:

   C:\Program Files\Windows Azure SDK\v1.0\samples\StorageClient

We will examine working with each of the storage services from the perspective of the StorageClient library - but keep in mind that ultimately this library is a wrapper around a basic and open RESTful API.

Setting The Stage: The Sample Application

To explore Azure Storage I have written a simple photo sharing distributed application. These set of applications allow users to upload photos to a photo sharing site. These photos must be reviewed and approved by moderators of the site. Once approved, the general public can view and interact with the photos. For a concrete example, you could imagine writing a distributed version of the wallpaper sharing site InterfaceLift and deploying it on Azure in this fashion.

You can download the sample application and follow along if you want to see the full source code and try it out yourself. Just be sure to start the Development Storage utility that comes with the Azure SDK before running the application.

Our distributed application consists of three parts.

  • The Uploader: A Windows Forms application that lets contributors upload images to the site.
  • The Reviewer: A Windows Forms application that lets moderators view image submissions and either approve or reject them.
  • The Website: An ASP.NET website for viewing the photos - this is our public facing application.

A typical use case might be as follows (see diagram below).

  1. We upload a photo submission with our uploader application. The photo is uploaded to Azure blob storage and a message is sent via an Azure Message Queue to all available reviewer applications. Additional information about the submitter is associated with the photo in Azure table storage.
  2. The reviewer application watches the message queue for new messages. When one arrives, the photo is added to a list of pending submissions. The reviewer can either reject (delete) the submission or approve it - move it to a permanent blob storage location where it will be publicly viewable.
  3. Users visit our website and can view all approved photos. This list will change in real-time because it is driven by the reviewer application. The web application simply pulls all photos from the approved photo container in Azure blob storage.

Saving Data: Creating Azure Blobs

To save data to Azure Blob Storage, you must realize blob storage follows the ACE pattern (Authority, Container, Entity) to describe a blob. Authority is simply your Azure solution name. Containers are analogous to folders. And entities are analogous to files.

The listing below is essentially the code that runs when the uploader application uploads a pending image submission to blob storage.

Listing 1:

Sending Notifications: Azure Queuing

In addition to uploading the image to the pending images container in blob storage, we will send a message to a message queue to notify any active or future reviewers of the new submission.

Listing 2.

Saving (More) Data: Structured Storage and Azure Tables

Finally, for the upload application, we must also save some information about the contributor. In Azure Storage we have two reasonable places to store this information.

First, we could save this information directly in blob storage as meta-data associated with the blob itself. This is straightforward and easy. But there is a big limitation: information in this meta-data is not queryable. Suppose I want get all images associated with a single contributor. There is no way in Azure Blob Storage to say give me all the blobs with this filter on the meta-data. You would have to pull the properties of every blob and do the comparison client-side. That's tantamount to filling a DataSet with "SELECT * FROM PendingImages" and it's a bad idea.

Instead we will use the third type of Azure Storage: Azure Table Storage. Table Storage allows us to store data with up to 256 properties and query this data as if it were a database. It is exactly what we need for the contributor information. However, you must realize this is not a database. A better mental picture is a durable collection of Dictionary object (as in Dictionary from System.Collections.Generics) with querying built on top. I say this because there is no schema or relational constructs in Azure Table Storage. If you need that, then you'll want Sql Data Services - a service on top of the core Azure platform.

The code to add an entry to Azure Table Storage does not fit into a single method as it's driven through the interaction of several classes we must define. Azure Table Storage can be accessed via ADO.NET Data Services (client-side) and this is the method we will use.

First we'll define a client-side schema for our entry by creating a class called Contributor which derives from the class TableStorageEntity (from the StorageClient library).

Listing 3.

Additionally we must define the tables and queries available to ADO.NET Data Services by created a class derived from TableStorageDataServiceContext and we do that below. We simply have one table called Contributors.

Listing 4.

With those two items in place, we can insert a "row" into Azure Table Storage as follows:

Listing 5.

As for querying Azure Table Storage that is very straight-forward. Because we are using ADO.NET Data Services, querying can be done via LINQ as in "from c in svc.Contributors select c.Name". Ultimately ADO.NET Data Services is also built on a RESTful API so this translates to the underlying HTTP REST calls. Alternatively, you can use that REST API directly from .NET or any other platform.

Waiting on Queues: The Reviewer Application's Code

Next, let's look at how we monitor and pull messages from Azure Queuing. Ultimately we must poll the queue using a RESTful HTTP request. But the StorageClient resurfaces this to us as simple events.

Listing 6.

We won't cover how we move a blob from the pendingImages blob container to the approvedImages blob container which happens when a reviewer approves an image. You can look at the sample to see how that is done.

Ultimately It's About the Website

Finally, let's look at the web application that actually displays the approved images. We don't do anything fancy such as paging or error handling that you'd see in a real application. But this will give you a good idea how to work with the blob data as a collection.

Here we'll create a BlobStorage object and access the BlobContainer approvedImageContainer as we have been in most of the listings. But then instead of saving or reading blobs, we use the ListBlobs method to simply list all the approve images in that container. In order to show the images on our webpage, we just use the BlobProperties.Uri and directly reference that in our HTML. Our ASP.NET application does not touch the data. Rather the consumers (IE, Firefox, Chrome, etc) of the HTML pull the image data directly from blob storage as they would from any web server.

Listing 7.

Now you have a good idea of the concepts and motivation behind Azure Storage. You have seen some typical usages of each of the three storage features: blob storage, table storage, and queuing. Our samples made use of the sample storage API library called StorageClient. Underlying this library we saw that Azure Storage is entirely accessed via RESTful APIs.

Want to get started? Visit http://www.azure.com and choose "Try It Now" to register for a CTP Azure account. You'll need to download the various SDK's listed on that same page. They will install the Visual Studio projects required for working with Azure as well as the Development Storage and Development Fabric so you can develop and debug your applications before deploying them to the cloud.

If you want some intensive, expert-lead training on Azure and associated .NET 4.0 topics be sure to contact DevelopMentor. Or call 800.699.1932 to find out what classes we have available today.

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

RESTful Web Services with WCF Screencast

Tuesday, March 24, 2009 11:02:03 AM (Pacific Standard Time, UTC-08:00)

I recently got the chance to record a screencast discussing REST-oriented web services in WCF. If you're interested in WCF you should definitely check it out because WCF and REST make an awesome combination. kennedy-wcf-rest-video-screenshot.png
   WCF-REST-Kennedy-Peepleocity.wmv 35 MB (WMV HD)

I cover building WCF services using REST princples, the WebGet and WebInvoke attributes, working with the SyndicationFeed & Rss20FeedFormatter classes, and configuration-free WCF hosting in IIS.

You can also download the source code of the project built in the screencast.

Finally, if you're willing to do without video you can download just the audio as an MP3.

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Debugging the Future (Advanced .NET Debugging) Video Presentation

Tuesday, March 03, 2009 3:14:04 PM (Pacific Standard Time, UTC-08:00)
My esteemed colleague, friend, and fellow instructor at DevelopMentor Jason Whittington gave a great presentation on advanced .NET debugging recently at the Oklahoma City Developer's Group. They luckily recorded it on video and published it on their website so that it may "live on in the Google".

   Debugging The Future: The Video by Jason Whittington

 
kick it on DotNetKicks.com

If you want to debug .NET applications right down to their memory footprint, this talk is for you.

If you like this type of presentation, be sure to check out the classes we offer at DevelopMentor.
Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

MSDN Magainze: Web Apps That Support Long-Running Operations

Wednesday, December 24, 2008 9:18:04 AM (Pacific Standard Time, UTC-08:00)
I'm pleased to announce that MSDN Magazine just published my Windows Workflow article entitled

    "ASP.NET WORKFLOW: Web Apps That Support Long-Running Operations"

I hope you find it useful and interesting.


Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

ClickOnce Deployment for Unmanaged Code (C++, VB6, etc)

Monday, August 25, 2008 7:53:30 PM (Pacific Standard Time, UTC-08:00)

ClickOnce is a great deployment model for many Windows applications built with the .NET Framework. Too bad it isn't supported for C++, VB 6, or other technologies. Or is it...

Surprisingly, you can deploy your unmanaged apps with ClickOnce. You just need a tiny .NET app to get it started.

Here's how it works:

  1. Take your existing C++ project.

  2. Add to the solution a .NET console application.

  3. Change the project settings on the console application to "Windows Application".

  4. Write the following code for your Main method of your .NET launcher application:
    static void Main(string[] args)
    {
        try
        {
            Process.Start( "TheRealApp.exe" );
        }
        catch ( Exception x )
        {
            string msg = "Error launch application:\n\n" + x;
            string cap = "Error Launching Application";
            MessageBox.Show( msg, cap, MessageBoxButtons.OK, MessageBoxIcon.Error );
        }
    }
    
  5. Set the build path of your C++ app to be in the main folder for your .NET application.

  6. Add the C++ app and its libraries (if any) as existing items in the .NET app.

  7. Change the build action to "Always Copy" as shown here:




  8. Then you publish your .NET application and when it runs, TADA!, the C++ app is deployed, versioned, and kept up to date as well.



If you want to try it yourself, you can run this sample application here:

   Run Michael's Useless C++ App via ClickOnce...

You can also download the source.



Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

ThreadPool Bug in .NET 2.0 SP1 is Fixed!

Wednesday, August 20, 2008 8:18:02 AM (Pacific Standard Time, UTC-08:00)

I'm glad to confirm that the ThreadPool bug introduced in .NET 3.5 has been fixed in SP1 for .NET 3.5.

For more background information, look at these posts.

  1. .NET 3.5 Brings Breaking Changes to ThreadPool
  2. Breaking Changes in the ThreadPool: The Movie
  3. Follow up on .NET 2.0 SP1 ThreadPool Bug
  4. More on the ThreadPool Bug in .NET 2.0 SP1

Now go forth, and create some threads!


Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Dynamic Data Access with LINQ

Wednesday, July 02, 2008 10:08:00 AM (Pacific Standard Time, UTC-08:00)
When I talk about LINQ people often ask whether it’s possible to have dynamic queries with LINQ. An example of this is presenting the user with a UI that allows them to optionally filter by some criteria or other and sort by some criteria. This was straightforward if you built-up a SQL string in code.

The compiled, static nature of LINQ makes dynamic queries appear difficult at first. They are not and this video and sample application shows you how to accomplish just this.


                        Screen shot of sample application

You can download the source code here:

           Kennedy-Dynamic-Linq.zip (88.34 KB)

And you can watch the screencast video here:

          Kennedy-Dynamic-Linq.wmv (35.7 MB)

Of course, if you like this post, please kick it: kick it on DotNetKicks.com


Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

More on the ThreadPool Bug in .NET 2.0 SP1

Thursday, April 17, 2008 8:31:28 AM (Pacific Standard Time, UTC-08:00)
There appears to be some confusion about this .NET 2.0 SP1 ThreadPool bug I found. Can you believe someone might be wrong on the internet?

If you’ve been following the posts (1, 2, 3), then you’ll know I was in touch with the key guys at Microsoft and the root of the problem is that if you create asynchronous work faster than the ThreadPool can create threads, then that work "misses" the SetMinThreads command and are created more slowly.

That is why the Thread.Sleep(1) probably solves the issue for you. If it doesn’t, sleep slightly longer. It’s a timing issue.

With this insight, you’ll see that this does not really affect true servers such as ASP.NET and WCF but does affect things like Delegate.BeginInvoke and friends called in quick succession.

In short, if your server handles more than 1,000 requests per second, during the first second of startup, then your server may run into this problem (ok, ok, more precisely, if your server handles more than 1 request / millisecond).

Let me address a few common concerns out there:
  • Is the sky falling? No.
  • Is it great situation? No.
  • Will be fixed with .NET 2.0 SP2? Yes
  • When? Maybe this summer, maybe later - they aren’t sure.
  • Does this affect WCF and ASP.NET? Probably not. The bug, no. The new ThreadPool behavior, yes.
  • Is there a work around? Yes, create threads more slowly. This is automatic on the server.

kick it on DotNetKicks.com

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Follow up on .NET 2.0 SP1 ThreadPool Bug

Monday, March 03, 2008 11:49:40 AM (Pacific Standard Time, UTC-08:00)
Here's a followup post on the .NET ThreadPool bug that I described here:

Breaking Changes in the ThreadPool: The Movie

I have been in touch with the guys who are in charge of the ThreadPool and they have both confirmed that this is a bug and that they are planning on fixing it in .NET 2.0 SP2 - but they are not sure of the timeline for its release.

In the meantime, Vance Morrison, a .NET Runtime Performance Architect at Microsoft, has given me this work-around.

Take this "broken" code:

	private static void UseThreadPool(int count)
        {
            for ( int i = 0; i < count; i++ )
            {
                ThreadPool.QueueUserWorkItem(
                    delegate { SlowMethod(); } );
            }
        }
And add a strategic Thread.Sleep and it's fixed:

	private static void UseThreadPool(int count)
        {
            for ( int i = 0; i < count; i++ )
            {
                ThreadPool.QueueUserWorkItem(
                    delegate { SlowMethod(); } );
Thread.Sleep(1);
            }
        }



Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Breaking Changes in the ThreadPool: The Movie

Tuesday, February 26, 2008 10:21:04 AM (Pacific Standard Time, UTC-08:00)
Well, my recent post on .NET 3.5 Brings BREAKING Changes to ThreadPool sparked quite a bit of interest in the .NET community.

But this is also something difficult to convince people of because it depends so heavily on configuration. The source code doesn't change, the environment does.

So I've put together a screencast demonstrating the problem and elaborating further. If you doubt the validity of the previous post, or can't reproduce the problem, please watch the video:




                     Download the video (approx 18 MB)

Kick it: kick it on DotNetKicks.com

In the video I work with a modified version of the program. Here's that for your enjoyment:

The application: NetThreading.exe (From Video).zip (2.59 KB)

The source code:
using System;
using System.Threading;

namespace NewThreadPoolBehavior
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Console.WriteLine( "Running on " + Environment.Version );
            int w, c;
            ThreadPool.GetMaxThreads( out w, out c );
            Console.WriteLine( "Max Currently: " + w + ", " + c );
            ThreadPool.GetMinThreads( out w, out c );
            Console.WriteLine( "Min Currently: " + w + ", " + c );

            Console.WriteLine( "Set min thread count 20? (y/n) " );
            string txt = Console.ReadLine();
            if ( txt == "y" )
            {
                Console.WriteLine( "Setting min to 20" );
                ThreadPool.SetMinThreads( 20, 100 );
                ThreadPool.GetMinThreads( out w, out c );
                Console.WriteLine( "Min Currently: " + w + ", " + c );
            }
            UseThreadPool( 200 );

            Console.ReadLine();
        }

        private static DateTime startTime;

        private static void UseThreadPool(int count)
        {
            startTime = DateTime.Now;
            for ( int i = 0; i < count; i++ )
            {
                ThreadPool.QueueUserWorkItem(
                    delegate { SlowMethod(); } );
            }
        }

        private static int concurrent = 0;

        private static void SlowMethod()
        {
            TimeSpan dt = DateTime.Now - startTime;
            concurrent++;
            Console.WriteLine( "Starting ops (" + concurrent + " concurrent, elapsed=" +
dt.TotalSeconds.ToString( "N3" ) + " sec.) " );
            Thread.Sleep( 20000 );
            Console.WriteLine( "Finished ops (" + concurrent + " concurrent)" );
            concurrent--;
        }
    }
}

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

.NET 3.5 Brings Breaking Changes to ThreadPool

Monday, February 25, 2008 3:47:28 PM (Pacific Standard Time, UTC-08:00)

[Note: This has been fixed in .NET 3.5 SP1, read more on this post.]

Holy smokes! I thought we had figured out something significant when I posted .NET 3.5 Brings Major (Undocumented) Changes to ThreadPool where we discovered that the .NET 3.5 ThreadPool changed the allocation algorithm for adding threads from linear to logarithmic.

This is bigger. [Recently updated see note below]

Here's the scenario. I have a server - say in the financial sector - that must process many requests and it must get up to speed immediately. I can't pay the 500 ms warm up time for the ThreadPool (.NET 2.0) or the even slower model in .NET 2.0 SP1. What do I do? I call ThreadPool.SetMinThreads(x, x) where x < (the current max), but much higher than 2 (the default). So I might call ThreadPool.SetMinThreads(100, 100) or something like that.

In .NET 1.0 - .NET 2.0 (without SP1) you would go from the warm up time model:


                 warm up time model (.NET 2.0)

To this immediate "ready" threading model.


                 ready model (.NET 2.0)

Notice that we immediately have 100 threads available in this case. BUT, and here's the but: .NET 3.5 (read .NET 2.0 SP1) *ignores* SetMinThreads. Oh, it claims to respect SetMinThreads:

   Running on 2.0.50727.1433
   Max Currently: 500, 1000
   Min Currently: 2, 2
   Set min thread count 100 (y/n)? y
   Setting min to 100
   Min Currently: 100, 100

But, look at the thread graph that results!


           ready model (.NET 2.0 SP1  -- i.e. .NET 3.5)

I don't know about you, but that doesn't look any different AT ALL than if we do not call SetMinThreads:


         warm up time model (.NET 2.0 SP1  -- i.e. .NET 3.5)

What do we conclude from this? .NET 2.0 SP1 does not respect ThreadPool.SetMinThreads. To me, that's a big breaking change. My financial app just stopped working. Yikes! So what happened to my thread pool and SetMinThreads in .NET 2.0 SP1? Anyone?

Kick it: kick it on DotNetKicks.com

Don't take my word for it. Run this program on both .NET 2.0 (SP0) and .NET 2.0 SP1 and you'll see for yourself.

Here's the EXE:

   NetThreading.zip (2.3 KB)

And the source code is below:
using System;
using System.Threading;

namespace NewThreadPoolBehavior
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Console.WriteLine( "Running on " + Environment.Version );
            int w, c;
            ThreadPool.GetMaxThreads( out w, out c );
            Console.WriteLine( "Max Currently: " + w + ", " + c );
            ThreadPool.GetMinThreads( out w, out c );
            Console.WriteLine( "Min Currently: " + w + ", " + c );

            Console.WriteLine( "Set min thread count 100? (y/n) " );
            string txt = Console.ReadLine();
            if ( txt == "y" )
            {
                Console.WriteLine( "Setting min to 100" );
                ThreadPool.SetMinThreads( 100, 100 );
                ThreadPool.GetMinThreads( out w, out c );
                Console.WriteLine( "Min Currently: " + w + ", " + c );
            }
            UseThreadPool( 200 );

            Console.ReadLine();
        }

        private static void UseThreadPool(int count)
        {
            for ( int i = 0; i < count; i++ )
            {
                ThreadPool.QueueUserWorkItem(
                    delegate { SlowMethod(); } );
            }
        }

        private static int concurrent = 0;

        private static void SlowMethod()
        {
            concurrent++;
            Console.WriteLine( "Starting ops (" + concurrent + " concurrent)" );
            Thread.Sleep( 20000 );
            Console.WriteLine( "Finished ops (" + concurrent + " concurrent)" );
            concurrent--;
        }
    }
}
[Update: 2/25/2008 - You may be thinking so what's the big deal? Most applications don't directly program against the ThreadPool so this is just some edge case. To make this more real for everyone, this applies to you if you use any of the following: ASP.NET, WCF, .NET Remoting, Delegate.BeginInvoke, SqlCommand.BeginExecute*, Windows Workflow, and more. Sounds serious now right?]

[Update: 5/12/2008 - Please see my lastest followup on this topic: More on the ThreadPool Bug in .NET 2.0 SP1.]


Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

.NET 3.5 Brings Major (Undocumented) Changes to ThreadPool

Wednesday, February 06, 2008 9:33:32 PM (Pacific Standard Time, UTC-08:00)

It was all going so smoothly. Jason Whittington, Mark Smith and I were teaching the big DevelopMentor event here in Los Angeles (Guerrilla.NET) when my presentation on the ThreadPool took a nose dive. It started with a great joke involving Wilson (the volleyball from Cast Away).

Wilson and I built an application to compute a multiplication table where each computation was (artificially) slow. To speed it up we threw it at the thread pool using delegate.BeginInvoke. We figured that the ThreadPool would allocate 25 or so threads and the table would display quickly. Here's the expected output - pretty much the same thing we've seen since about .NET 1.0:

    

Each color represents the thread that did that computation.

For the last 7 years, the behavior has been that as the ThreadPool was overloaded, it would steadily start up new threads at the rate of one every 500 milliseconds until it hits its upper limit (typically). Using Performance Monitor (perfmon) we can watch the thread pool adding threads. It usually looks something like this:

    

Much to our surprise we saw completely different behavior. The thread pool added the first 15 or so threads quickly (as expected) but then stalled. New threads were not created every 500ms, instead they were added at increasingly long intervals. My demo took almost twice as long to run as it had the last time I did this demo a few months ago.

Jason, Mark, and I took this code, ported it back to .NET 1.1 and ran it side-by-side with .NET 3.5 and here's what we saw (blue = 3.5, red = 1.1):

    

As of .NET 3.5 the upper limit of the ThreadPool was increased: Knew that.

But, it appears that v3.5 of the CLR changes the policy for adding threads to the thread pool. Rather than adding threads regularly when under load the thread pool uses a logarithmic backoff. My colleague Jason Whittington remarked that this behavior looked similar to the behavior of the thread pool in "Rotor" (the shared-source version of the CLR). We speculated that this backoff algorithm makes sense given the new 250-thread per CPU maximum - it would take a long time to reach that if the runtime waits longer and longer to start a new thread. The 250-thread limits makes it less likely that your application will deadlock the thread pool, and the exponential backoff algorithm keeps the thread pool from creating too many threads too quickly.

Why should you care? Usually you won't, but it could have dramatic impact if you count on that behavior. For example, in our contrived case, .NET 1.1 ran about twice as fast as .NET 3.5 ( ! ):

    

Here's the program and source code (trimmed down to run in both .NET 1.1 and 3.5).

    Math.zip (6.38 KB)

Needless to say, Wilson and I felt kinda stood up.

      kick it on DotNetKicks.com

Please see the follow up post on Breaking changes and now there is screencast, movie version as well.


Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post

Guerrilla.NET Demos and Challenges

Wednesday, February 06, 2008 9:09:38 AM (Pacific Standard Time, UTC-08:00)
Thanks to everyone who attended Guerrilla .NET last week. I had a great time meeting all of you. Here are the slides and demos from all our presentations.

     Demos.rar (22 MB)

    Challenge.rar (8 MB)

- Michael

Tweet this Follow me on Twitter Post this to dotnetshoutout.com Digg this Submit this to Stumbleupon email this post


Just a site note: I'm doing my part to rid the world of IE 6. Visit this site with IE 6 and you'll get a shameful message telling you to "Stop Living in the Past".