<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>b#: Blog</title><link>http://flux88.com/blog/</link><description /><generator>Graffiti CMS 1.1 (build 1.1.0.1114)</generator><lastBuildDate>Thu, 09 Jul 2009 19:04:33 GMT</lastBuildDate><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/flux88" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><title>Detecting a tap on a UITextView</title><link>http://feedproxy.google.com/~r/flux88/~3/8bJMLW5L9O0/</link><pubDate>Thu, 09 Jul 2009 18:04:33 GMT</pubDate><guid isPermaLink="false">http://flux88.com/blog/detecting-a-tap-on-a-uitextview/</guid><dc:creator>benscheirman</dc:creator><slash:comments>0</slash:comments><category domain="http://flux88.com/blog/">Blog</category><description>&lt;p&gt;I’ve been working on a little side project (that I’ll announce soon).&amp;#160; It is an iPhone application that I intend to sell.&amp;#160; Being a .NET guy, I’m certainly a bit lost when it comes to troubleshooting problems.&amp;#160; Hopefully this post will help someone else out that ran into a similar issue.&lt;/p&gt;  &lt;p&gt;In Cocoa, any class that derives from UIResponder (which means UIView and all of it’s subclasses) can get touch events by implementing these 4 optional methods:&lt;/p&gt;  &lt;pre class="brush: cpp; gutter: false; toolbar: false;"&gt;- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;&lt;/pre&gt;

&lt;p&gt;With this raw data you can construct any number of touch schemes, such as knowing when to scroll and when to select something, as is the case with UITableView.&lt;/p&gt;

&lt;p&gt;UIControl derivatives (such as UIButton) get a simpler abstraction:&amp;#160; they use that data &amp;amp; translate it to different events such as &lt;codetouchdowninside&gt;&amp;lt; code&amp;gt;and &lt;code&gt;touchUpInside&lt;/code&gt;.&amp;#160; These don’t work for all views, so sometimes to detect a tap you have to roll your own.&lt;/p&gt;

&lt;p&gt;In general, you can just look at the touchesEnded event and check the tapCount property to see if the user tapped an element:&lt;/p&gt;

&lt;pre class="brush: cpp; gutter: false; toolbar: false;"&gt;-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
   UITouch *touch = [touches anyObject]; //assume just 1 touch
   if(touch.tapCount == 1) {
      //single tap occurred
   }
}&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;a href="http://flux88.com/files/media/image/WindowsLiveWriter/DetectingataponaUITextView_8AB1/uitextview_4.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px; display: inline; border-top: 0px; border-right: 0px" title="uitextview" border="0" alt="uitextview" align="right" src="http://flux88.com/files/media/image/WindowsLiveWriter/DetectingataponaUITextView_8AB1/uitextview_thumb_1.png" width="229" height="283" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wanted to use this on a view that contained a full-screen UITextView.&amp;#160; &lt;/p&gt;

&lt;p&gt;Unfortunately, as of the iPhone SDK 3.0, UITextView swallows this event completely.&amp;#160; I imagine because of the new feature where you can select text to copy &amp;amp; paste.&amp;#160; You can get touchesBegan, touchesMoved, and touchesCancelled, but no touchesEnded.&amp;#160; (In fact, the touch actually gets cancelled by the UITextView).&amp;#160; Even by subclassing UITextView I could not get this event.&lt;/p&gt;

&lt;p&gt;Luckily I found a work-around.&amp;#160; It’s not exactly pretty, but it works for me.&lt;/p&gt;

&lt;p&gt;First I needed to subclass UIWindow so that I can get control at the very beginning of every touch.&lt;/p&gt;

&lt;p&gt;Next I needed to change my MainViewController.xib, which creates the window, to point to my new class.&lt;/p&gt;

&lt;p&gt;Then, in the sendEvent method, I need to check for 3 things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;is this touch ending?&lt;/li&gt;

  &lt;li&gt;is this touch hitting my custom text view?&lt;/li&gt;

  &lt;li&gt;is this touch a single tap?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here' is the code for my custom window:&lt;/p&gt;

&lt;pre class="brush: cpp; gutter: false; toolbar: false;"&gt;//CustomWindow.h
@interface CustomWindow : UIWindow {
}

@end

//CustomWindow.m

#import &amp;quot;CustomTextView.h&amp;quot;

@implementation CustomWindow

-(void)sendEvent:(UIEvent *)event {
   //loop over touches for this event
   for(UITouch *touch in [event allTouches]) {
      BOOL touchEnded = (touch.phase == UITouchPhaseEnded);
      BOOL isSingleTap = (touch.tapCount == 1);
      BOOL isHittingCustomTextView = 
           (touch.view.class == [CustomTextView class]);

      if(touchEnded &amp;amp;&amp;amp; isSingleTap &amp;amp;&amp;amp; isHittingCustomTextView) {
         CustomTextView *tv = (CustomTextView*)touch.view;
         [tv tapOccurred:touch withEvent:event];
      }
   }
}&lt;/pre&gt;

&lt;pre class="brush: cpp; gutter: false; toolbar: false;"&gt;@end&lt;/pre&gt;

&lt;p&gt;If all the 3 BOOLs turn out to be true, then I simply call a method I defined on my CustomTextView.&lt;/p&gt;

&lt;p&gt;This CustomTextView then calls a similar method on it’s tapDelegate (which I created).&amp;#160; My view controller then adheres to the TapDelegateProtocol (which contains this method) and can now detech taps over a UITextView!&lt;/p&gt;

&lt;p&gt;Now my textview becomes fullscreen when you tap it, and another tap brings back the tab bar at the bottom and navigation bar at the top.&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e51873d5-b699-4cc4-832d-e6102c491eba" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/iPhone" rel="tag"&gt;iPhone&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Cocoa" rel="tag"&gt;Cocoa&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Objective-C" rel="tag"&gt;Objective-C&lt;/a&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/flux88?a=8bJMLW5L9O0:jpcvaljCh6g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=8bJMLW5L9O0:jpcvaljCh6g:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=8bJMLW5L9O0:jpcvaljCh6g:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?i=8bJMLW5L9O0:jpcvaljCh6g:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><feedburner:origLink>http://flux88.com/blog/detecting-a-tap-on-a-uitextview/</feedburner:origLink></item><item><title>Getting Started with Heroku on Windows</title><link>http://feedproxy.google.com/~r/flux88/~3/PlSq-e74jUw/</link><pubDate>Wed, 10 Jun 2009 17:57:12 GMT</pubDate><guid isPermaLink="false">http://flux88.com/blog/getting-started-with-heroku-on-windows/</guid><dc:creator>benscheirman</dc:creator><slash:comments>4</slash:comments><category domain="http://flux88.com/blog/">Blog</category><description>&lt;p&gt;&lt;a href="http://heroku.com" target="_blank"&gt;Heroku&lt;/a&gt; looks to be a very promising way of writing Rails applications with easy deployment, source control, and hosting all built-in.&lt;/p&gt;  &lt;p&gt;Unfortunately, the windows story of &lt;a href="http://rubyonrails.org" target="_blank"&gt;Rails&lt;/a&gt; development, &lt;a href="http://rubygems.org" target="_blank"&gt;ruby gems&lt;/a&gt;, &lt;a href="http://git-scm.com/" target="_blank"&gt;Git&lt;/a&gt;, &lt;a href="http://www.sqlite.org/" target="_blank"&gt;SQLite&lt;/a&gt;, are all incredibly horrible, and make it tough to get started.&amp;#160; Wish I were &lt;a href="http://flux88.com/blog/upgrading-my-hackintosh-to-10-5-7/" target="_blank"&gt;on a Mac&lt;/a&gt;, but yeah… not on my laptop… yet.&lt;/p&gt;  &lt;h3&gt;Step 1:&amp;#160; Install &lt;a href="http://www.cygwin.com/" target="_blank"&gt;Cygwin&lt;/a&gt;&lt;/h3&gt;  &lt;p&gt;I can’t stress enough how awesome this tool is.&amp;#160; it gives you a unix-style shell that supports a number of things, namely Git.&amp;#160; You can’t run Git on windows without msys-git or similar and it is required for Heroku.&amp;#160; &lt;em&gt;(Git is the deployment mechanism for packaging up your changes and sending them to Heroku)&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;When you install cygwin, make sure to expand the packages and install *at least* the following:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;gcc &lt;/li&gt;    &lt;li&gt;gcc-g++ &lt;/li&gt;    &lt;li&gt;git &lt;/li&gt;    &lt;li&gt;git-completion &lt;/li&gt;    &lt;li&gt;git-gui &lt;/li&gt;    &lt;li&gt;gitk &lt;/li&gt;    &lt;li&gt;grep &lt;/li&gt;    &lt;li&gt;gzip &lt;/li&gt;    &lt;li&gt;libsqlite3-devel &lt;/li&gt;    &lt;li&gt;libsqlite3_0 &lt;/li&gt;    &lt;li&gt;make &lt;/li&gt;    &lt;li&gt;man &lt;/li&gt;    &lt;li&gt;openssh &lt;/li&gt;    &lt;li&gt;ruby&amp;#160; &amp;lt;—some say this is buggy, but it seems to work for me &lt;/li&gt;    &lt;li&gt;sqlite3 &lt;/li&gt;    &lt;li&gt;tar &lt;/li&gt;    &lt;li&gt;wget &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Wait for it to download and install those packages.&amp;#160; There might be others, but those are the major ones installed on my machine.&amp;#160; If you already have cygwin installed, you can run the setup.exe file again and select the packages you’re missing.&lt;/p&gt;  &lt;h3&gt;Step 2:&amp;#160; Install Rubygems&lt;/h3&gt;  &lt;p&gt;Note that this is required even if you already have the one-click ruby installer on windows.&amp;#160; Steven Harman wrote about &lt;a href="http://stevenharman.net/blog/archive/2008/11/12/installing-rubygems-in-cygwin.aspx" target="_blank"&gt;how to do this in cygwin&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;ol&gt;     &lt;li&gt;&lt;em&gt;Download the RubyGems tarball from &lt;/em&gt;&lt;a href="http://rubyforge.org/projects/rubygems/"&gt;&lt;em&gt;Ruby Forge&lt;/em&gt;&lt;/a&gt; &lt;/li&gt;      &lt;li&gt;&lt;em&gt;Unpack the tarball &lt;/em&gt;&lt;/li&gt;      &lt;li&gt;&lt;em&gt;In a bash terminal, navigate to the unpacked directory &lt;/em&gt;&lt;/li&gt;      &lt;li&gt;&lt;em&gt;Run the following command:&lt;/em&gt;         &lt;pre&gt;&lt;em&gt;ruby setup.rb install&lt;/em&gt;&lt;/pre&gt;
    &lt;/li&gt;

    &lt;li&gt;&lt;em&gt;Update RubyGems by running the following:&lt;/em&gt; 

      &lt;pre&gt;&lt;em&gt;gem update --system&lt;/em&gt;&lt;/pre&gt;
    &lt;/li&gt;
  &lt;/ol&gt;

  &lt;p&gt;&lt;em&gt;Note: You may need to run the updated command twice if you have any previously installed gems.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note, if you try to run some ruby files and you get a “could not load rubygems” error, you may need to unset the RUBYOPT environment variable.&amp;#160; The windows version might be conflicting with the cygwin version.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;Step 3:&amp;#160; Install sqlite3-ruby gem&lt;/h3&gt;

&lt;p&gt;The sqlite3-ruby gem is actually a CGem (not ruby) so it needs a windows binary. Unfortunately, there isn’t a windows version yet, so you need to back up to the latest one that does, which is 1.2.3 as of this post.&lt;/p&gt;

&lt;pre&gt;gem install sqlite3-ruby –v 1.2.3&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If this fails with an error saying “looking for sqlite.h…no” then you probably haven’t installed the libsqlite3_devel package in cygwin. This tripped me up.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;Step 4: Install json gem&lt;/h3&gt;

&lt;p&gt;Again, the latest version of this gem doesn’t work yet with Windows, so you have to request version 1.1.1.&lt;/p&gt;

&lt;pre&gt;gem install json –v 1.1.1&lt;/pre&gt;

&lt;h3&gt;&amp;#160;&lt;/h3&gt;

&lt;h3&gt;Step 5: Install Heroku gem&lt;/h3&gt;

&lt;pre&gt;gem install heroku&lt;/pre&gt;

&lt;h3&gt;&amp;#160;&lt;/h3&gt;

&lt;h3&gt;Step 6: Create an SSH key file&lt;/h3&gt;

&lt;p&gt;In order to communicate securely with heroku, you need to create an SSH key file.&lt;/p&gt;

&lt;pre&gt;$ cd ~/
$ mkdir .ssh
$ cd .ssh
$ ssh-keygen –C “my key” –t rsa&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;This should create a public &amp;amp; private key file.&amp;#160; Heroku will look for this.&lt;/p&gt;

&lt;p&gt;Now we can follow the standard heroku instructions, which are pretty simple.&amp;#160; Here’s how you’d create a sample rails app, initialize git, add files, and create the app on heroku.&amp;#160; Finally we’ll push the code &amp;amp; you can see it running online.&lt;/p&gt;

&lt;pre&gt;$ rails foo
$ cd foo
$ git init
$ git add .
$ git commit –m “adding files”
$ heroku create (type in heroku credentials when prompted)
$ git push heroku master&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;You’ll be given a URL when you create the app on heroku, so after you push you can visit &lt;a href="http://your-app-name.heroku.com"&gt;http://your-app-name.heroku.com&lt;/a&gt; to see it live!&lt;/p&gt;

&lt;p&gt;Hope this helps someone else get started faster than me!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/flux88?a=PlSq-e74jUw:R5fMkxk09dM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=PlSq-e74jUw:R5fMkxk09dM:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=PlSq-e74jUw:R5fMkxk09dM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?i=PlSq-e74jUw:R5fMkxk09dM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><feedburner:origLink>http://flux88.com/blog/getting-started-with-heroku-on-windows/</feedburner:origLink></item><item><title>jQuery Autocomplete with a Hidden Value</title><link>http://feedproxy.google.com/~r/flux88/~3/hYwlp0lbxMU/</link><pubDate>Tue, 02 Jun 2009 13:34:20 GMT</pubDate><guid isPermaLink="false">http://flux88.com/blog/jquery-autocomplete-with-a-hidden-value/</guid><dc:creator>benscheirman</dc:creator><slash:comments>3</slash:comments><category domain="http://flux88.com/blog/">Blog</category><description>&lt;p&gt;A number of people commented on my post about a &lt;a href="http://flux88.com/blog/jquery-auto-complete-text-box-with-asp-net-mvc/"&gt;jQuery Autocomplete Textbox in ASP.NET MVC&lt;/a&gt; wanting to know how to provide a value for the items being displayed.&amp;#160; It’s not an uncommon request.&amp;#160; For many pieces of data you’ll have display values as well as unique identifiers to distinguish &amp;amp; provide reference to the items.&lt;/p&gt;  &lt;p&gt;Unfortunately it’s not well document, however this is fully supported with &lt;a href="http://dyve.net/jquery/?autocomplete"&gt;Dylan Verheul’s jQuery autocomplete plugin&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The first step is to separate your display names from the values in your result from the server.&amp;#160; We were retuning cities before, like this:&lt;/p&gt;  &lt;pre&gt;HOUSTON, AK 
HOUSTON, AL 
HOUSTON, TX 
HOUCK, AR 
HOUGHTON, IA&lt;/pre&gt;

&lt;p&gt;The individual items are separated by a new line character.&amp;#160; In order to provide a value for each of these, you have to separate the item with a pipe “|”.&lt;/p&gt;

&lt;pre&gt;HOUSTON, AK&lt;strong&gt;|456&lt;/strong&gt; 
HOUSTON, AL&lt;strong&gt;|1245&lt;/strong&gt; 
HOUSTON, TX&lt;strong&gt;|553&lt;/strong&gt; 
HOUCK, AR&lt;strong&gt;|99&lt;/strong&gt; 
HOUGHTON, IA&lt;strong&gt;|401&lt;/strong&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;If your display items might contain a pipe character, then you’ll have to change the separator setting for the plugin.&amp;#160; You can do by providing the option &lt;strong&gt;cellSeparator&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now that our items have a value coming back from the server, how can we retrieve it when an item is selected?&amp;#160; That is done via the onSelectItem function.&amp;#160; This is a callback that will send you the formatted &amp;lt;li&amp;gt; tag.&amp;#160; If there was a value specified, it will be placed in the &lt;em&gt;extra&lt;/em&gt; attribute.&lt;/p&gt;

&lt;p&gt;Here’s an example:&lt;/p&gt;

&lt;p&gt;$(cities).autocomplete(action_url, {
  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; lineSeparator: '\n',

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; cellSeparator: '|',

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; onItemSelect: function(li) {&amp;#160; if(li.extra) alert(&amp;quot;You selected &amp;quot; + li.extra[0]); }

  &lt;br /&gt; });&lt;/p&gt;

&lt;p&gt;I’ve specified the options for lineSeparator and cellSeparator.&amp;#160; These are the default values, but you can easily change them if the character is a valid portion of the text being returned by the server. &lt;/p&gt;

&lt;p&gt;You can use this handler to place the selected value in a hidden field to save it for a form submission.&lt;/p&gt;

&lt;p&gt;Hope this helps!&amp;#160; For more information, I suggest you read the source code and examine the &lt;a href="http://dyve.net/jquery/?autocomplete" target="_blank"&gt;plugin page source&lt;/a&gt; for more examples.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/flux88?a=hYwlp0lbxMU:KdLcnfacHI8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=hYwlp0lbxMU:KdLcnfacHI8:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=hYwlp0lbxMU:KdLcnfacHI8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?i=hYwlp0lbxMU:KdLcnfacHI8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><feedburner:origLink>http://flux88.com/blog/jquery-autocomplete-with-a-hidden-value/</feedburner:origLink></item><item><title>Hello Isaac &amp; Isabella!</title><link>http://feedproxy.google.com/~r/flux88/~3/beQp35S4PeE/</link><pubDate>Mon, 01 Jun 2009 14:33:19 GMT</pubDate><guid isPermaLink="false">http://flux88.com/blog/hello-isaac-38-isabella/</guid><dc:creator>benscheirman</dc:creator><slash:comments>14</slash:comments><category domain="http://flux88.com/blog/">Blog</category><description>&lt;p&gt;Last saturday, our twins were born!&lt;/p&gt;
&lt;p&gt;&lt;img src="http://flux88.com/files/media/image/IMG_3937.jpg" width="480" height="320" alt="IMG_3937" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Isaac Sawyer Scheirman (5 lbs 1 oz, born at 7:32 PM Saturday 5/23/2009)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;br /&gt;
&lt;img src="http://flux88.com/files/media/image/IMG_3893.jpg" width="480" height="320" alt="Isabella" /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Isabella Rose Scheirman (4 lbs 10 oz, born at 7:34 PM on 5/23/2009)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The babies were 6 weeks premature, so they're still in the hospital. They're both healthy, good lung development, they can maintain their temperature, etc. They just need to gain some more weight so they can come home!&lt;/p&gt;
&lt;p&gt;Needless to say, I've been incredibly busy... :)&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;I've uploaded more photos are &lt;a href="http://www.flickr.com/photos/bensilvia/sets/72157618845380244/"&gt;up on flickr&lt;/a&gt; if you're interested.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/flux88?a=beQp35S4PeE:Us59oFZY57k:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=beQp35S4PeE:Us59oFZY57k:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=beQp35S4PeE:Us59oFZY57k:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?i=beQp35S4PeE:Us59oFZY57k:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><feedburner:origLink>http://flux88.com/blog/hello-isaac-38-isabella/</feedburner:origLink></item><item><title>Upgrading my Hackintosh to 10.5.7</title><link>http://feedproxy.google.com/~r/flux88/~3/8Hy3VF_nYm4/</link><pubDate>Wed, 13 May 2009 18:08:41 GMT</pubDate><guid isPermaLink="false">http://flux88.com/blog/upgrading-my-hackintosh-to-10-5-7/</guid><dc:creator>benscheirman</dc:creator><slash:comments>7</slash:comments><category domain="http://flux88.com/blog/">Blog</category><description>&lt;p&gt;I updated &lt;a href="http://flux88.com/blog/building-a-hackintosh/"&gt;my Hackintosh&lt;/a&gt; to &lt;a href="http://support.apple.com/kb/HT3397"&gt;OS X 10.5.7&lt;/a&gt; last night.&amp;#160; Luckily I had just backed up my system volume with SuperDuper the night before, so I felt confident in doing the update.&lt;/p&gt;  &lt;p&gt;Usually updates are the bane of any hack-users existence (I wouldn’t exactly call myself a hacker, as I simply leverage smart peoples’ work).&amp;#160; Updates to OS X generally replace hacked kexts, or add new road bumps that prevent previous hacks from working properly.&lt;/p&gt;  &lt;p&gt;In my case, the upgrade went very smoothly.&amp;#160; The system rebooted (twice for some reason) and I was able to log back in.&lt;/p&gt;  &lt;p&gt;My sound didn’t work, so I loaded up &lt;a href="http://cheetha.net/"&gt;Kext Helper&lt;/a&gt; and loaded up these two kexts again:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.mediafire.com/?zijzedz4rym"&gt;HDAEnabler&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.filefactory.com/file/afgeac5/n/ALC888_4A_out_amp_2A_1D_in_1_6_2_a37_zip"&gt;Custom AppleHDA&lt;/a&gt; for my Realtek ALC888 onboard sound card&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;(luckily I saved these from previous endeavors)&lt;/p&gt;  &lt;p&gt;My drive icons were all orange (as if they were external USB drives instead of internal SATA ones), so I installed this fix to restore their normal icons: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://pcwizcomputer.com/index.php?option=com_docman&amp;amp;task=doc_details&amp;amp;gid=82&amp;amp;Itemid=74"&gt;http://pcwizcomputer.com/index.php?option=com_docman&amp;amp;task=doc_details&amp;amp;gid=82&amp;amp;Itemid=74&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Everything seems to be running perfectly smooth.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://flux88.com/files/media/image/WindowsLiveWriter/UpgradingmyHackintoshto10.5.7_B8D6/image_8.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://flux88.com/files/media/image/WindowsLiveWriter/UpgradingmyHackintoshto10.5.7_B8D6/image_thumb_3.png" width="308" height="500" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;As an aside, a lot of folks have asked me how my hackintosh is treating me.&amp;#160; Is the honeymoon phase over?&amp;#160; Yes and no.&amp;#160; The system is not without it’s flaws.&amp;#160; I only recently got my microphone to work, and I still haven’t been able to get 5.1 surround to work (which is pretty low on my important-things-to-do list).&amp;#160; My printer doesn’t work, so I’m relegated to printing from XP in VMWare Fusion.&amp;#160; I still need to purchase a nice webcam that works with OS X.&lt;/p&gt;  &lt;p&gt;I still thoroughly enjoy using OS X, even more so than Windows 7.&amp;#160; The software is just that much more polished.&lt;/p&gt;  &lt;p&gt;For development, it kind of sucks to have to be in Windows to use Visual Studio.&amp;#160; MonoDevelop may get there one day, or perhaps JetBrains will unload an awesome cross-platform .NET IDE.&amp;#160; Who knows.&lt;/p&gt;  &lt;p&gt;The last thing I miss are games.&amp;#160; I’ve been seriously considering cancelling my World of Warcraft account, due to lack of time… but I’d still like to play an FPS or two when they come out, and it looks like I’ll have to dual boot if I want to do that, since they’re almost never on the Mac.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/flux88?a=8Hy3VF_nYm4:hDqZmArNnss:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=8Hy3VF_nYm4:hDqZmArNnss:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=8Hy3VF_nYm4:hDqZmArNnss:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?i=8Hy3VF_nYm4:hDqZmArNnss:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><feedburner:origLink>http://flux88.com/blog/upgrading-my-hackintosh-to-10-5-7/</feedburner:origLink></item><item><title>A Culture of Microcomponents</title><link>http://feedproxy.google.com/~r/flux88/~3/OBT5NYcIhrU/</link><pubDate>Fri, 01 May 2009 18:16:35 GMT</pubDate><guid isPermaLink="false">http://flux88.com/blog/a-culture-of-microcomponents/</guid><dc:creator>benscheirman</dc:creator><slash:comments>16</slash:comments><category domain="http://flux88.com/blog/">Blog</category><description>&lt;p&gt;Imagine that you are given the opportunity to rewrite (or upgrade with extreme prejudice) one of your older .NET 2.0 (or 1.1) projects using .NET 3.5.&amp;nbsp; You wrote it, so you have intimate knowledge of the current architecture, what parts smell, what works well.&amp;nbsp; You know what custom components you wrote to solve various problems, etc.&amp;nbsp; You also have a ton of lessons learned.&amp;nbsp; Now you get to do again, only this time you have more advanced, sharper tools at your disposal.&lt;/p&gt; &lt;p&gt;&lt;img style="margin: 0px 20px" align="right" src="http://www.blackwagon.com/Merchant2/graphics/00000001/BRIO010-brio-building-blocks-natural-lg.jpg"&gt;I went through this process recently and came up with no shortage of 3rd party libraries I wanted to use for the new version:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="https://www.hibernate.org/343.html" target="_blank"&gt;NHibernate&lt;/a&gt;  &lt;li&gt;&lt;a href="http://fluentnhibernate.org/" target="_blank"&gt;Fluent NHibernate&lt;/a&gt;  &lt;li&gt;&lt;a href="http://sourceforge.net/projects/nhcontrib/" target="_blank"&gt;NHibernate.Linq&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.castleproject.org/container/index.html" target="_blank"&gt;Castle Windsor&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.castleproject.org/activerecord/documentation/v1rc1/usersguide/validation.html" target="_blank"&gt;Castle Validators&lt;/a&gt;  &lt;li&gt;&lt;a href="http://logging.apache.org/log4net/index.html" target="_blank"&gt;log4net&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.codeplex.com/AutoMapper" target="_blank"&gt;AutoMapper&lt;/a&gt;  &lt;li&gt;&lt;a href="http://code.google.com/p/elmah/" target="_blank"&gt;ELMAH&lt;/a&gt;  &lt;li&gt;&lt;a href="http://mvccontrib.org" target="_blank"&gt;MvcContrib&lt;/a&gt;  &lt;li&gt;&lt;a href="http://sparkviewengine.com/" target="_blank"&gt;Spark&lt;/a&gt;  &lt;li&gt;&lt;a href="http://jquery.com/" target="_blank"&gt;jQuery&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.atblabs.com/jquery.corners.html" target="_blank"&gt;jQuery rounded corners&lt;/a&gt; &lt;li&gt;&lt;a href="http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/" target="_blank"&gt;jQuery auto-complete&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.codeplex.com/CommonServiceLocator" target="_blank"&gt;CommonServiceLocator&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.codeplex.com/LINQtoAD" target="_blank"&gt;LINQ to ActiveDirectory&lt;/a&gt;  &lt;li&gt;&lt;a href="http://docu.jagregory.com/" target="_blank"&gt;docu&lt;/a&gt;  &lt;li&gt;&lt;a href="http://nunit.org" target="_blank"&gt;NUnit&lt;/a&gt;  &lt;li&gt;&lt;a href="http://nant.sf.net" target="_blank"&gt;NAnt&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;This list is nothing to sneeze at, and it's just what I could remember... in fact it's probably a bit longer.&amp;nbsp; This tends to scare people, as it is a lot of stuff to learn.&amp;nbsp; &lt;em&gt;What the heck are these things?&amp;nbsp; Where did they come from?&amp;nbsp; Do I need it?&amp;nbsp; How do I learn it?&amp;nbsp; Why did you include this?&lt;/em&gt;&lt;/p&gt; &lt;p&gt;That's a great question.&amp;nbsp; &lt;strong&gt;Why &lt;em&gt;do&lt;/em&gt; I want to use all of these things?&lt;/strong&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;I firmly believe in leveraging the work of others, and writing code that is expressive and easy to maintain.&amp;nbsp; Some of these projects exist solely to make working with another item from the list a lot easier.&amp;nbsp; NHibernate is a great example.&amp;nbsp; I loves me some NHibernate, but writing XML mapping files by hand isn't what I'd call a fun time.&amp;nbsp; Fluent NHibernate makes this so much nicer.&amp;nbsp; The last thing I want to do is reinvent the wheel.&lt;/p&gt; &lt;p&gt;&lt;img style="margin: 20px" src="http://liambest.com/square.jpg" width="419" height="480"&gt;&lt;/p&gt; &lt;p&gt;I don't think I'm alone here.&amp;nbsp; Most projects I come across have a similar attitude regarding re-using rather than re-inventing.&amp;nbsp; Most come with a dozen or so additional libraries so that it can function.&amp;nbsp; I recently asked on twitter how many 3rd party libraries folks are using.&amp;nbsp; The average result was about 5, but some were as high as 12.&lt;/p&gt; &lt;p&gt;The bottom line for me is:&amp;nbsp; &lt;strong&gt;The value I get from leveraging 3rd party tools is greater than the psychic weight that they cause.&amp;nbsp; &lt;/strong&gt;But others may not agree with me.&lt;/p&gt; &lt;p&gt;What about the Ruby community?&amp;nbsp; Don't they have this problem?&amp;nbsp; Absolutely.&amp;nbsp; But I don't think they would classify it as a problem, and I'd tend to agree.&amp;nbsp; Say you're writing a ruby app and you somehow want to integrate flickr with twitter and paypal.&lt;/p&gt;&lt;pre class="csharpcode"&gt;&amp;gt; gem install flickr
&amp;gt; gem install twitter
&amp;gt; gem install paypal
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;&lt;img style="margin: 0px 20px" align="right" src="http://www.workingwithrails.com/images/ruby-gem.png?1213632569"&gt;...Wait what?&amp;nbsp; That's it?&amp;nbsp; Yep.&amp;nbsp; &lt;strong&gt;&lt;a href="http://rubygems.org/" target="_blank"&gt;Rubygems&lt;/a&gt; is a thing of beauty&lt;/strong&gt;.&amp;nbsp; It lowers the barrier to installing 3rd party plugins and libraries.&amp;nbsp; Rails plugins has a similar concept.&amp;nbsp; Need to rate one of your models?&amp;nbsp; &lt;pre&gt;script/install plugin acts_as_rateable&lt;/pre&gt; Want to use jQuery instead of prototype/scriptaculous?&amp;nbsp; simply run &lt;pre&gt;script/install plugin jrails&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;These techniques allow you to add small pieces of functionality to existing applications with relative ease.&amp;nbsp; You don't have to open a web browser &amp;amp; search for the tool.&amp;nbsp; You don't have to download &amp;amp; extract it somewhere.&amp;nbsp; And you don't need to copy it into your project tree.&amp;nbsp; Everything is done with a single command.&lt;/p&gt;
&lt;p&gt;It seems as if every concept and service has their own gem or rails plugin.&amp;nbsp; Rails applications today can be built rather simply by composing tiny pieces of functionality written by other people.&amp;nbsp; &lt;br&gt;&lt;/p&gt;
&lt;p&gt;So why can't we do this in .NET?&amp;nbsp; Well in short, we can... but it requires a culture shift.&amp;nbsp; For starters, in .NET we generally check in all of our dependencies into source control, so that we can always guarantee that each developer has all of the required tools (and the specific versions of such tools).&amp;nbsp; With ruby gems, each gem is installed into a common location, which is consistent across all machines (actually it is configurable, but the point is it's a global directory).&amp;nbsp; To use one of the gems installed on your machine, you simply do this:&lt;/p&gt;&lt;pre class="csharpcode"&gt;require &lt;span class="str"&gt;'hpricot'&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;It knows to load up that library from a central location.&amp;nbsp; When this application is deployed to another environment, the same thing occurs.&amp;nbsp; Gems are installed via the same commands as on the dev machines. &lt;/p&gt;
&lt;p&gt;Back at ALT.NET Seattle 2009 I convened a session to discuss revitalizing one of the many &lt;em&gt;gems-for-.NET&lt;/em&gt; projects.&amp;nbsp; We identified several efforts along similar lines as gems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ngems 
&lt;li&gt;cogs 
&lt;li&gt;nu 
&lt;li&gt;horn 
&lt;li&gt;Machine.PartStore&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt; Out of this discussion, a few folks decided to start fresh with a new project (affectionately called &lt;a href="http://github.com/scottcreynolds/rocks/tree/master" target="_blank"&gt;rocks&lt;/a&gt;), and toy with getting rubygems to work with IronRuby and wrapping it all in our own command line interface.&amp;nbsp; Not much has been done on this except a quick spike, but I think the idea is promising.&lt;/p&gt;
&lt;p&gt;I believe that if something like this comes up in the .NET community it will lead to a shift in how we think about dependencies, components, and overall re-use of small pieces of code to build larger applications.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;What do you think?&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/flux88?a=OBT5NYcIhrU:ULUJmwpTK1E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=OBT5NYcIhrU:ULUJmwpTK1E:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=OBT5NYcIhrU:ULUJmwpTK1E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?i=OBT5NYcIhrU:ULUJmwpTK1E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><feedburner:origLink>http://flux88.com/blog/a-culture-of-microcomponents/</feedburner:origLink></item><item><title>Awarded INETA Community Champion for Q1 2009</title><link>http://feedproxy.google.com/~r/flux88/~3/NCzbmXtvAVQ/</link><pubDate>Sun, 26 Apr 2009 23:47:30 GMT</pubDate><guid isPermaLink="false">http://flux88.com/blog/awarded-ineta-community-champion-for-q1-2009/</guid><dc:creator>benscheirman</dc:creator><slash:comments>3</slash:comments><category domain="http://flux88.com/blog/">Blog</category><description>&lt;p&gt;Just a small announcement:&amp;nbsp; I was recently awarded the INETA Community Champion Award!&amp;nbsp; I'm finding that my community work is rewarding in many ways.&amp;nbsp; Over the past couple years I have met so many influential people that have helped me (inadvertently) build my own career.&amp;nbsp; I sincerely hope that any efforts I make in the community have a similar effect to others.&lt;/p&gt; &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="ineta-community-champion" src="http://flux88.com/files/media/image/WindowsLiveWriter/AwardedINETACommunityChampionforQ12009_10840/ineta-community-champion_0bd55d8d-c604-407b-93c3-ba9e3d22cf61.jpg" width="360" height="350"&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/flux88?a=NCzbmXtvAVQ:SsPMueHNBKE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=NCzbmXtvAVQ:SsPMueHNBKE:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=NCzbmXtvAVQ:SsPMueHNBKE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?i=NCzbmXtvAVQ:SsPMueHNBKE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><feedburner:origLink>http://flux88.com/blog/awarded-ineta-community-champion-for-q1-2009/</feedburner:origLink></item><item><title>jQuery Auto-Complete Text Box with ASP.NET MVC</title><link>http://feedproxy.google.com/~r/flux88/~3/8wea2Te7W6Q/</link><pubDate>Tue, 21 Apr 2009 14:55:01 GMT</pubDate><guid isPermaLink="false">http://flux88.com/blog/jquery-auto-complete-text-box-with-asp-net-mvc/</guid><dc:creator>benscheirman</dc:creator><slash:comments>23</slash:comments><category domain="http://flux88.com/blog/">Blog</category><description>&lt;blockquote&gt; &lt;p&gt;&lt;img alt="clip_image004" align="left" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExcerptfromASP.NETMVCinActionChapter6_ED7F/clip_image004_e87da01d-98f6-479d-b891-3b4df10d5fa6.jpg"&gt;&lt;em&gt;This is an excerpt from Chapter 13 in my upcoming book, &lt;/em&gt;&lt;a href="http://manning.com/palermo" target="_blank"&gt;&lt;em&gt;ASP.NET MVC in Action&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p style="clear: both"&gt;_________________________________________________ &lt;p style="clear: both"&gt;These days it is not uncommon to have text boxes automatically suggest items based on what we type. The results are further filtered as we type to give us the option to simply select an available item with the mouse or keyboard. One of the first examples of this in the wild was Google Suggest.  &lt;p&gt;&lt;img border="0" alt="clip_image002" src="http://flux88.com/files/media/image/WindowsLiveWriter/jQueryAutoCompleteTextBoxwithASP.NETMVC_8B6F/clip_image002_1f1897ba-a575-4c10-8a33-bc2cdf2cb3bb.gif" width="504" height="415"&gt;  &lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 13.1 Google Suggest filters options as you type &lt;/strong&gt;&lt;/em&gt; &lt;p&gt;A rudimentary implementation of this would simply monitor key-presses and fire off ajax requests for each one. Of course this means that fast typist would trigger many requests, most of which would be immediately discarded for the next request coming in 5 milliseconds. A good implementation will take into account a typing delay and also provide keyboard/mouse support for selecting the items.  &lt;p&gt;Luckily jQuery has an extensive list of plugins available. One such plugin is Dylan Verheul’s autocomplete.  &lt;blockquote&gt; &lt;p&gt;&lt;strong&gt;Dylan Verheul’s autocomplete&lt;/strong&gt;  &lt;p&gt;You can download the autocomplete plugin at &lt;a href="http://www.dyve.net/jquery/?autocomplete"&gt;http://www.dyve.net/jquery/&lt;/a&gt; along with a few others including googlemaps and listify. &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The basic idea is you have a simple text box on your page. The jQuery plugin adds the necessary behavior to handle key press events and fire the appropriate Ajax requests off to a URL that will handle the request. The URL needs point to a controller action, and by convention the response is formatted in a special way so the plugin could handle the response.  &lt;p&gt;Assume for our purposes that we wanted to filter US Cities in the text box. The first step is to add a controller, action, and view for displaying the UI for this example. Ensure that jquery (in this case jquery-1.2.6.js) and jquery.autcomplete.js are referenced at the top of the view (or master page). &lt;pre class="csharpcode"&gt;&amp;lt;script type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt; src=&lt;span class="str"&gt;"../../scripts/jquery-1.2.6.js"&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt; src=&lt;span class="str"&gt;"../../scripts/jquery.autocomplete.js"&lt;/span&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;Next, add the text box. In this example we will call it city. &lt;pre class="csharpcode"&gt;&amp;lt;%= Html.TextBox(&lt;span class="str"&gt;"city"&lt;/span&gt;) %&amp;gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;Package this up with a simple controller (Listing 13.1). 
&lt;p&gt;&lt;strong&gt;Listing 13.1 – a controller &amp;amp; action for displaying our test page&lt;/strong&gt; &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; HomeController : Controller 
{ 
     &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Index() 
     { 
          &lt;span class="kwrd"&gt;return&lt;/span&gt; View(); 
     } 
} 
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;&lt;img border="0" alt="clip_image004" src="http://flux88.com/files/media/image/WindowsLiveWriter/jQueryAutoCompleteTextBoxwithASP.NETMVC_8B6F/clip_image004_0cfb60e7-12e0-4a33-932e-c034304bfcc7.jpg" width="425" height="244"&gt; 
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Figure 13.2 – Our simple view with a text box.&lt;/em&gt;&lt;/strong&gt; 
&lt;p&gt;Now we add a little Javascript to add the autocomplete behavior. &lt;pre class="csharpcode"&gt;&amp;lt;script type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt;&amp;gt; 

$(document).ready(&lt;span class="kwrd"&gt;function&lt;/span&gt;() { 
     $(&lt;span class="str"&gt;"input#city"&lt;/span&gt;).autocomplete(&lt;span class="str"&gt;'&amp;lt;%= Url.Action("Find", "City") %&amp;gt;'&lt;/span&gt;); 
}); 

&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt; 
&lt;p&gt;Place this in the &amp;lt;head&amp;gt; of the page. You can see that the URL for the autocomplete behavior is specified as Url.Action("Find", "City"). This will point to a Find() action on the CityController. We'll need to write this controller &amp;amp; action next. 
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Local Data Mode&lt;/strong&gt; 
&lt;p&gt;The autocomplete plugin can also filter local data structures. This is useful when you have a limited set of data and you want to minimize requests sent to the server. The autcomplete plugin in local mode is also much faster, since there is no Ajax request happening behind the scenes. The only downside is that you must render the entire array onto the view. &lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Listing 13.3 – An action to find cities from an autocomplete ajax request&lt;/strong&gt; &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CityController : Controller 
{ 
  &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; ICityRepository _repository; 
  
  &lt;span class="kwrd"&gt;public&lt;/span&gt; CityController() 
  { 
    &lt;span class="rem"&gt;//load up a CSV file with the city data&lt;/span&gt;
    &lt;span class="kwrd"&gt;string&lt;/span&gt; csvPath = Server.MapPath(&lt;span class="str"&gt;"~/App_Data/cities.csv"&lt;/span&gt;);
    
    &lt;span class="rem"&gt;//the repository reads the csv file&lt;/span&gt;
    _repository = &lt;span class="kwrd"&gt;new&lt;/span&gt; CityRepository(csvPath); #2 
  } 

  &lt;span class="rem"&gt;//this constructor allows our tests to pass in a fake/mock instance&lt;/span&gt;
  &lt;span class="kwrd"&gt;public&lt;/span&gt; CityController(ICityRepository repository) #3 
  { 
    _repository = repository; 
  } 

  &lt;span class="rem"&gt;//the autocomplete request sends a parameter 'q' that contains the filter&lt;/span&gt;
  &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Find(&lt;span class="kwrd"&gt;string&lt;/span&gt; q) #4 
  { 
    &lt;span class="kwrd"&gt;string&lt;/span&gt;[] cities = _repository.FindCities(q); 
    
    &lt;span class="rem"&gt;//return raw text, one result on each line&lt;/span&gt;
    &lt;span class="kwrd"&gt;return&lt;/span&gt; Content(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Join(&lt;span class="str"&gt;"\n"&lt;/span&gt;, cities));
  } 
} &lt;/pre&gt;
&lt;p&gt;The details of the CityRepository can be found in the code samples provided with the book. For now, we will focus on the new Find(string q) action. Since this is a standard action, you can actually just navigate to it in your browser and test it out. Figure 13.3 shows a quick test. 
&lt;p&gt;&lt;img border="0" alt="clip_image006" src="http://flux88.com/files/media/image/WindowsLiveWriter/jQueryAutoCompleteTextBoxwithASP.NETMVC_8B6F/clip_image006_1a0c89de-76d8-4270-8354-81e3d31bde72.jpg" width="516" height="330"&gt; 
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Listing 13.3 – A simple HTTP GET for the action with a filter of "hou" yields the expected results.&lt;/em&gt;&lt;/strong&gt; 
&lt;p&gt;Now that we are sure that the action is returning the correct results, we can test the textbox. The Javascript we added earlier hooks up to the keypress events on the textbox and should issue queries to the server. Figure 13.4 shows this in action. 
&lt;p&gt;&lt;img border="0" alt="clip_image008" src="http://flux88.com/files/media/image/WindowsLiveWriter/jQueryAutoCompleteTextBoxwithASP.NETMVC_8B6F/clip_image008_d9311a77-e166-4950-84eb-e689316fa5df.jpg" width="422" height="489"&gt; 
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Figure 13.4 – The results are display in a &amp;lt;ul&amp;gt; tag. We can apply CSS to make it look nicer. &lt;/em&gt;&lt;/strong&gt;
&lt;p&gt;The drop down selections are unformatted by default, which makes them a little ugly. A little CSS magic will make it look much nicer. Listing 13.4 shows some sample CSS for this. 
&lt;p&gt;&lt;strong&gt;Listing 13.4 – CSS used to style the autocomplete results &lt;/strong&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;style&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="text/css"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; 

div.ac_results ul { 
  margin:0; 
  padding:0; 
  list-style-type:none; 
  border: solid 1px #ccc; 
} 

div.ac_results ul li { 
  font-family: Arial, Verdana, Sans-Serif; 
  font-size: 12px; 
  margin: 1px; 
  padding: 3px; 
  cursor: pointer; 
} 

div.ac_results ul li.ac_over { 
  background-color: #acf; 
} 

&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;style&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; 

&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;&lt;img border="0" alt="clip_image010" src="http://flux88.com/files/media/image/WindowsLiveWriter/jQueryAutoCompleteTextBoxwithASP.NETMVC_8B6F/clip_image010_cdcec9f1-d7ec-460f-8c72-94b3bb9ec65b.jpg" width="422" height="489"&gt; 
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Figure 13.5 – The styled dropdown results look much nicer. The selected item is highlighted, and can be chosen with the keyboard or the mouse. &lt;/em&gt;&lt;/strong&gt;
&lt;p&gt;The auto-complete plug-in has many options for you to configure to your needs. For the simple case that we've shown here, it's as simple as this: &lt;pre class="csharpcode"&gt;$(your_textbox).autocomplete(&lt;span class="str"&gt;'your/url/here'&lt;/span&gt;); &lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;Other options for the plugin are listed below: &lt;/p&gt;
&lt;table border="1" cellspacing="0" cellpadding="4" width="400"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;inputClass &lt;/td&gt;
&lt;td valign="top" width="200"&gt;This class will be added to the input box. &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;resultsClass &lt;/td&gt;
&lt;td valign="top" width="200"&gt;default value: "ac_results" &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;loadingClass &lt;/td&gt;
&lt;td valign="top" width="200"&gt;The class to apply to the input box while results are being fetched from the server. Default is “ac_loading.” &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;lineSeparator &lt;/td&gt;
&lt;td valign="top" width="200"&gt;Default is \n &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;minChars &lt;/td&gt;
&lt;td valign="top" width="200"&gt;The minimum # of characters before sending a request to the server. Default is 1. &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="200"&gt;delay &lt;/td&gt;
&lt;td valign="top" width="200"&gt;The delay after typing when the request will be sent. Default is 400ms. &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&amp;nbsp; &lt;p&gt;There are many more options, but these are some common ones. To set these options, you include them in a dictionary as the second argument to the autocomplete method like this: &lt;pre class="csharpcode"&gt;$(&lt;span class="str"&gt;"input#city"&lt;/span&gt;).autocomplete(&lt;span class="str"&gt;'&amp;lt;%= Url.Action("Find", "City") %&amp;gt;'&lt;/span&gt;, { 
     minChars : 3, 
     delay : 300 
}); 

&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;This type of functionality is immensely useful for selecting from large lists. It keeps your initial page size down by not loading all of these items at once and is very user-friendly. 
&lt;p&gt;________________________________________
&lt;p&gt;&lt;img alt="clip_image004" align="left" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExcerptfromASP.NETMVCinActionChapter6_ED7F/clip_image004_e87da01d-98f6-479d-b891-3b4df10d5fa6.jpg"&gt;&lt;em&gt;This is an excerpt from Chapter 13 in my upcoming book, &lt;/em&gt;&lt;a href="http://manning.com/palermo" target="_blank"&gt;&lt;em&gt;ASP.NET MVC in Action&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/flux88?a=8wea2Te7W6Q:I6wKe-_tLu0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=8wea2Te7W6Q:I6wKe-_tLu0:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=8wea2Te7W6Q:I6wKe-_tLu0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?i=8wea2Te7W6Q:I6wKe-_tLu0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><feedburner:origLink>http://flux88.com/blog/jquery-auto-complete-text-box-with-asp-net-mvc/</feedburner:origLink></item><item><title>Exporting Visual Studio Solutions with SolutionFactory</title><link>http://feedproxy.google.com/~r/flux88/~3/p6GTflZFtR4/</link><pubDate>Mon, 13 Apr 2009 16:20:29 GMT</pubDate><guid isPermaLink="false">http://flux88.com/blog/exporting-visual-studio-solutions-with-solutionfactory/</guid><dc:creator>benscheirman</dc:creator><slash:comments>10</slash:comments><category domain="http://flux88.com/blog/">Blog</category><description>&lt;p&gt;&lt;img style="margin: 0px 15px 20px 20px" align="right" src="http://www.weblims.com/Portals/4/visual%20studio.png" width="67" height="40"&gt;&lt;/p&gt; &lt;p&gt;Part of my job is to create reusable code, patterns, designs, solutions, etc for other developers to leverage.&amp;nbsp; Getting started using some of these things can be initially tough for someone who hasn't had a lot of experience with long-term, maintainable solution structures for projects that use:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;an automated build  &lt;li&gt;3rd party libraries  &lt;li&gt;machine-specific configuration  &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself" target="_blank"&gt;D.R.Y.&lt;/a&gt; for things like connection strings, etc.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Because of these things, I favor a folder structure similar to this one:&lt;/p&gt; &lt;p&gt;&lt;img border="0" alt="image" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExportingVisualStudioSolutionswithSoluti_F340/image_146df75b-7e7a-46d3-b3a5-bfe159f7ad44.png" width="532" height="529"&gt; &lt;/p&gt; &lt;p&gt;This keeps things tidy.&amp;nbsp; There is a home for everything.&amp;nbsp; Third party libraries get checked in to source control, as well as any light-weight developer tools that we use during the build.&amp;nbsp; Everything you need to build the software on a developer's machine should be here.&amp;nbsp; (&lt;em&gt;Of course I assume that you already have the appropriate Visual Studio &amp;amp; database server on your local machine.)&lt;/em&gt;&lt;/p&gt; &lt;p&gt;In addition, &lt;strong&gt;many&lt;/strong&gt; of our projects look something like this:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;App.UI  &lt;li&gt;App.Core  &lt;li&gt;App.Persistence  &lt;li&gt;App.Tests&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Granted, this is very short-sighted and won't be the end-all-be-all solution structure for all projects.&amp;nbsp; &lt;strong&gt;But the goal here is to get you (a developer) started really quickly&lt;/strong&gt;.&amp;nbsp; These projects can already contains some things that get from nothing to something tangible in short time.&lt;/p&gt; &lt;p&gt;My sample solution contains:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;An MVC project with a standard look &amp;amp; feel  &lt;ul&gt; &lt;li&gt;images  &lt;li&gt;javascript files&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;A sample CRUD screen, showing a small example of the various players in displaying &amp;amp; updating data.  &lt;ul&gt; &lt;li&gt;NHibernate  &lt;li&gt;FluentNHibernate  &lt;li&gt;NHibernate.Linq  &lt;li&gt;an IOC container  &lt;li&gt;an MVC Controller factory&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;A test project that shows both unit and integration style tests.&amp;nbsp; Some nice fluent testing extensions are left in to show how it works. (the target audience will probably only have a C# 2.0 background).&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;All of this is pre-wired up.&amp;nbsp; Dependencies are referenced in each project.&amp;nbsp; The libraries are located in a relative URL, meaning other people who check out this code can build immediately.&amp;nbsp; In addition, there is a sample NAnt script that shows how to build &amp;amp; test the software.&lt;/p&gt; &lt;p&gt;It's about convention over configuration.&amp;nbsp; For some applications, if they don't want to do it this way, fine.&amp;nbsp; It's not about enforcement, it's about gentle guidance &amp;amp; encouragement.&lt;/p&gt; &lt;h2&gt;Packaging it all up&lt;/h2&gt; &lt;p&gt;&lt;img style="margin: 0px 15px 15px 0px" align="left" src="http://static.guim.co.uk/sys-images/Travel/Pix/pictures/2007/01/22/Hell_Alamy460.jpg" width="240" height="144"&gt;So I went on the path of trying to export this into a set of Visual Studio project templates.&amp;nbsp; I found the project templates to be less-than helpful for a few reasons.&amp;nbsp; First, it assumes that you keep your projects in the root of the project folder structure.&amp;nbsp; Second, there seemed to be no way to elegantly package up assemblies that the project depended on.&amp;nbsp; I looked at &lt;a href="http://code.google.com/p/sharp-architecture/" target="_blank"&gt;S#arp Architecture&lt;/a&gt; for some help, but quickly realized that there isn't an easy road to doing all of this.&amp;nbsp; In addition, as far as I could tell there is no way to automatically create solution templates.&amp;nbsp; You have to create project templates for each project and then manually stitch them together.&lt;/p&gt; &lt;p&gt;This violated my #1 rule with the templates.&amp;nbsp; &lt;strong&gt;In order for them to be successful, they must be really easy to change&lt;/strong&gt;.&amp;nbsp; I figure that in 2 months time, something in the template will have changed, or someone will want to tweak the design, or upgrade to a new version of a dependant assembly.&amp;nbsp; If they have to go through all of those hoops to publish a new template, they just won't do it.&amp;nbsp; All of the effort on the initial template will be wasted.&lt;/p&gt; &lt;p&gt;&lt;img style="margin: 15px 100px 15px 15px" border="0" alt="Factory-Yellow-256x256" align="right" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExportingVisualStudioSolutionswithSoluti_F340/Factory-Yellow-256x256_dae50722-4932-4e9b-a70c-9f3883ba7050.png" width="100" height="100"&gt;Then I came across &lt;a href="http://solutionfactory.codeplex.com" target="_blank"&gt;SolutionFactory&lt;/a&gt;, which is a project started by &lt;a href="http://www.lostechies.com/blogs/hex/" target="_blank"&gt;Eric Hexter&lt;/a&gt; up on &lt;a href="http://codeplex.com" target="_blank"&gt;Codeplex&lt;/a&gt;.&amp;nbsp; It consists of 2 major components:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;A template wizard that handles all of the post-launch tasks, such as moving the projects to the right location, fixing up references, etc.  &lt;li&gt;A Visual Studio add-in that creates a large solution template, containing multiple vstemplate files (project templates) and also respects my folder structure.&amp;nbsp; Nice!&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Usage is pretty dead simple.&amp;nbsp; After installing, you get a new add-in.&amp;nbsp; You have to enable the add-in before using it.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;img border="0" alt="image" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExportingVisualStudioSolutionswithSoluti_F340/image_ee84c045-c405-4380-aa89-8e4d54bc1d61.png" width="609" height="545"&gt; &lt;/p&gt; &lt;p&gt;&lt;img border="0" alt="image" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExportingVisualStudioSolutionswithSoluti_F340/image_202a8bd8-c38a-44a2-936c-e9bf8633bb46.png" width="542" height="358"&gt; &lt;/p&gt; &lt;p&gt;Once you place the checkmark next to the Solution Factory add-in and click OK, you should see a new menu item in Visual Studio.&lt;/p&gt; &lt;p&gt;&lt;img border="0" alt="image" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExportingVisualStudioSolutionswithSoluti_F340/image_d9932ca2-4bf1-4919-862f-c56d8874b0cd.png" width="712" height="545"&gt; &lt;/p&gt; &lt;p&gt;When you select "Export Template" from the Solution Factory menu, you are presented with this dialog:&lt;/p&gt; &lt;p&gt;&lt;img border="0" alt="image" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExportingVisualStudioSolutionswithSoluti_F340/image_898ce309-7205-469d-bfe9-479a7fe22b79.png" width="574" height="545"&gt; &lt;/p&gt; &lt;p&gt;This controls your exported VSI file.&amp;nbsp; One cool thing to note is that you can have a custom command run as part of the template invocation process.&amp;nbsp; This is especially helpful if you have a firstTimeConfig.bat file or similar.&amp;nbsp; Sometimes you just have to run the build once to make sure everything is in place.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;During the export, any remnants of TFS source control will be stripped out in the target folder&lt;/strong&gt;.&amp;nbsp; Any read-only files will be unlocked, any *.*scc files will be deleted, and *.csproj files will be modified to remove the source control bindings.&amp;nbsp; If this isn't done, you'll be prompted to remove source control bindings for each project every time you create a new project based on the template.&amp;nbsp; Yuck!&lt;/p&gt; &lt;p&gt;When the export is finished (it takes about a minute) you should see a message box like this:&lt;/p&gt; &lt;p&gt;&lt;img border="0" alt="image" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExportingVisualStudioSolutionswithSoluti_F340/image_334964b7-3f86-4a73-9401-c47554670e03.png" width="186" height="130"&gt; &lt;/p&gt; &lt;p&gt;Now if we look in our &lt;strong&gt;c:\temp&lt;/strong&gt; folder, we should see some new files:&lt;/p&gt; &lt;p&gt;&lt;img border="0" alt="image" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExportingVisualStudioSolutionswithSoluti_F340/image_b0d52aef-5cd9-4d96-8ab4-73f70a9cfc5f.png" width="158" height="67"&gt; &lt;/p&gt; &lt;p&gt;The VSI is a &lt;em&gt;Visual Studio Installer&lt;/em&gt; file, and it simplifies putting the template zip file into Visual Studio.&amp;nbsp; All you really have to do is copy it to the appropriate Visual Studio 2008\Templates folder and run devenv.exe /installvstemplates to get it to rebuild the template cache.&amp;nbsp; When you run the VSI, you'll get a simple installer.&amp;nbsp; &lt;strong&gt;It will warn you that the template is not signed, just press OK&lt;/strong&gt;.&lt;/p&gt; &lt;p&gt;There is one caveat though:&amp;nbsp; Our template relies on SolutionFactory.Wizard.dll to run some custom actions when the template is invoked.&amp;nbsp; The VSI file doesn't have permissions to copy files into C:\Program Files, so until a custom installer (MSI) is made, you have to copy this dll manually.&lt;/p&gt; &lt;p&gt;To do this, close down all instances of Visual Studio and copy SolutionFactory.Wizard.dll into c:\program files\Microsoft Visual Studio 9.0\Common 7\IDE\Private Assemblies.&amp;nbsp; (on Vista/7 this path may be different, so adjust accordingly).&amp;nbsp; This only has to be done once, and subsequent uses of the template will use this dll.&lt;/p&gt; &lt;p&gt;Now, fire up a fresh copy of Visual Studio, choose File-&amp;gt;New Project, and see our new template!&lt;/p&gt; &lt;p&gt;&lt;img border="0" alt="image" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExportingVisualStudioSolutionswithSoluti_F340/image_5d06788c-0d01-4147-b773-e5d9200d4f58.png" width="681" height="496"&gt; &lt;/p&gt; &lt;p&gt;When you click OK, Visual Studio will do a little dance, make sure you wait for it to finish!&amp;nbsp; When it's all done, you'll end up with this:&lt;/p&gt; &lt;p&gt;&lt;img border="0" alt="image" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExportingVisualStudioSolutionswithSoluti_F340/image_744bafa8-d6c6-4025-8a7e-4daea6ab88d8.png" width="638" height="480"&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Every thing is completely packaged up, with multiple projects, 3rd party libraries, tools, and an automated build.&amp;nbsp; The best part is that we can keep the template up to date and re-publish easily.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/flux88?a=p6GTflZFtR4:9hDMRgYISVA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=p6GTflZFtR4:9hDMRgYISVA:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=p6GTflZFtR4:9hDMRgYISVA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?i=p6GTflZFtR4:9hDMRgYISVA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><feedburner:origLink>http://flux88.com/blog/exporting-visual-studio-solutions-with-solutionfactory/</feedburner:origLink></item><item><title>Excerpt from ASP.NET MVC in Action Chapter 6</title><link>http://feedproxy.google.com/~r/flux88/~3/ItWhzAmeFSE/</link><pubDate>Thu, 09 Apr 2009 13:11:23 GMT</pubDate><guid isPermaLink="false">http://flux88.com/blog/excerpt-from-asp-net-mvc-in-action-chapter-6/</guid><dc:creator>benscheirman</dc:creator><slash:comments>3</slash:comments><category domain="http://flux88.com/blog/">Blog</category><description>&lt;p&gt;&lt;i&gt;Extending URL Routing in ASP.NET MVC&lt;/i&gt;  &lt;p&gt;Excerpted from  &lt;p&gt;&lt;img border="0" hspace="12" alt="clip_image004" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExcerptfromASP.NETMVCinActionChapter6_ED7F/clip_image004_e87da01d-98f6-479d-b891-3b4df10d5fa6.jpg" width="190" height="238"&gt;  &lt;p&gt;&lt;a href="http://manning.com/palermo/"&gt;ASP.NET MVC in Action&lt;/a&gt;  &lt;p&gt;&lt;img border="0" hspace="12" alt="clip_image005" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExcerptfromASP.NETMVCinActionChapter6_ED7F/clip_image005_1ad1421a-e8c2-4bda-8544-5d3dfff458b6.gif" width="212" height="24"&gt;  &lt;p&gt;&lt;b&gt;Jeffrey Palermo, Ben Scheirman, and Jimmy Bogard&lt;/b&gt;  &lt;blockquote&gt; &lt;p&gt;This article is taken from the book &lt;a href="http://manning.com/palermo/"&gt;ASP.NET MVC in Action&lt;/a&gt; from Manning Publications. One of the greatest aspects of ASP.NET MVC is its flexibility. Among other things, this gives us the capability to customize standard components. In this article, we'll take a look at how URL routing functions, and then explore how to enhance it to behave differently. For the book’s table of contents, the Author Forum, and other resources, go to &lt;a href="http://manning.com/palermo/"&gt;http://manning.com/palermo/&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The UrlRouteModule is an HttpModule and represents the entry point into the ASP.NET MVC Framework. This module examines each request, builds up the RouteData for the request, finds an appropriate IRouteHandler for the given route matched, and finally redirects the request to the IRouteHandler's IHttpHandler. Make sense?  &lt;p&gt;Our default route looks like Listing 1. The MapRoute method is actually a simplified way of specifying routes. The same route can be specified with more detail, as is shown in Listing 2.  &lt;p&gt;&lt;strong&gt;Listing 1 – a simple way of specifying routes&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;routes.MapRoute("default", "{controller}/{action}/{id}", 
    new { Controller="home", Action="index", id=""});&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Listing 2 – a more detailed way of specifying routes&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;routes.Add(new Route("{controller}/{action}/{id}",
    new RouteValueDictionary(new { Controller = "home", Action = "index", id = "" }),
    new MvcRouteHandler()));&lt;/pre&gt;
&lt;p&gt;That third argument in Listing 2 is telling the framework which &lt;code&gt;IRouteHandler&lt;/code&gt; to use for this route. We are using the built-in MvcRouteHandler that ships with the framework. By default we are using this class when using the MapRoute method. We can change this to be a custom route handler and take control in interesting ways. An IRouteHandler's responsibility is to create an appropriate IHttpHandler to handle the request given the details of the request. This is a good place to change the way routing works, or perhaps to gain control extremely early in the request pipeline. The MvcRouteHandler simply constructs an MvcHandler to handle a request, passing it a RequestContext, which contains the RouteData and IHttpContext. 
&lt;p&gt;A quick example will help illustrate the need for a custom route handler. When starting out defining your routes, you'll sometimes run across errors. Let's assume you also have the route shown in Listing 3 defined. 
&lt;p&gt;&lt;strong&gt;Listing 3 – Adding another route&lt;/strong&gt; &lt;pre class="csharpcode"&gt;routes.MapRoute(&lt;span class="str"&gt;"conferenceKey"&lt;/span&gt;, &lt;span class="str"&gt;"{conferenceKey}/{action}"&lt;/span&gt;, 
    &lt;span class="kwrd"&gt;new&lt;/span&gt; { Controller = &lt;span class="str"&gt;"Conference"&lt;/span&gt;, Action=&lt;span class="str"&gt;"index"&lt;/span&gt; }); 

&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;Here we’ve added a new custom route at the top position. What does it do? This will accept URLs like /HoustonCodeCamp2008/register and use the conference controller and call the register action on it, passing in the conferenceKey as a parameter to the action. 
&lt;p&gt;&lt;strong&gt;Listing 4 – a controller action that handles the new route &lt;/strong&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ConferenceController : Controller 
{ 
    &lt;span class="rem"&gt;/* snip */&lt;/span&gt; 

    &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Register(&lt;span class="kwrd"&gt;string&lt;/span&gt; conferenceKey) 
    { 
        &lt;span class="kwrd"&gt;return&lt;/span&gt; View(); 
    } 
} 

&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;This is a good example of a custom route that makes your URLs a lot more readable. 
&lt;p&gt;Now let's assume that we have another controller called Home. HomeController has an index action to show the start page. 
&lt;p&gt;&lt;strong&gt;Listing 5 – A controller action to respond to the default route &lt;/strong&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; HomeController : Controller 
{ 
    &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Index() 
    { 
        &lt;span class="kwrd"&gt;return&lt;/span&gt; View(); 
    } 

    &lt;span class="rem"&gt;/* snip */&lt;/span&gt; 
} 

&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;We'd like the URL for the action in Listing 4 to look like /home/index. If we try this URL, we'll get a 404 error, as shown in figure 1. Why? 
&lt;p&gt;&lt;img border="0" alt="clip_image007" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExcerptfromASP.NETMVCinActionChapter6_ED7F/clip_image007_7c3f0a18-341c-45ed-9a52-5a5d8db8e413.jpg" width="568" height="476"&gt; 
&lt;p&gt;&lt;strong&gt;Figure 1 - This message doesn’t tell us much about what’s wrong. An action couldn’t be found on the controller, but which one?. &lt;/strong&gt;
&lt;p&gt;It's not apparent from that error message what the problem is. We certainly have a controller called HomeController, and it has an action method called Index(). If you dig deep and take a look at the routes we can deduce that this URL was picked up by the first route, /{conferenceKey}/{action}, which was not what we intended. We should be able to indentify quickly when we have a routing mismatch, so that we can fix it more quickly. 
&lt;p&gt;With lots of custom routes, it is easy for a URL to be caught by the wrong route. Wouldn't it be nice if we had a diagnostics tool to display which routes are being matched (and used) for quickly catching these types of errors? 
&lt;p&gt;What we’d like to do is have an extra query string parameter that we can tack on if we want to see the route information. The current route information is stored in an object called RouteData, which is available to us in the IRouteHandler interface. The route handler is also first to get control of the request, so it is a great place to intercept and alter the behavior for any route. 
&lt;p&gt;&lt;strong&gt;Listing 6 – A custom route handler creates an associated IHttpHandler &lt;/strong&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CustomRouteHandler : IRouteHandler 
{ 
    &lt;span class="kwrd"&gt;public&lt;/span&gt; IHttpHandler GetHttpHandler(RequestContext requestContext) 
    { 
        &lt;span class="kwrd"&gt;if&lt;/span&gt;(HasQueryStringKey(&lt;span class="str"&gt;"routeInfo"&lt;/span&gt;, requestContext.HttpContext.Request)) 
        { 
            OutputRouteDiagnostics(requestContext.RouteData, requestContext.HttpContext); 
        } 
        
        var handler = &lt;span class="kwrd"&gt;new&lt;/span&gt; CustomMvcHandler(requestContext); 
        &lt;span class="kwrd"&gt;return&lt;/span&gt; handler; 
    } 

    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; HasQueryStringKey(&lt;span class="kwrd"&gt;string&lt;/span&gt; keyToTest, HttpRequestBase request) 
    { 
        &lt;span class="kwrd"&gt;return&lt;/span&gt; Regex.IsMatch(request.Url.Query, &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;@"^\?{0}$"&lt;/span&gt;, keyToTest)); 
    } 

    &lt;span class="rem"&gt;/* snip */&lt;/span&gt; 
} &lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;A route handler’s normal responsibility is to construct and hand-off the IHttpHandler that will handle this request. By default, this is MvcHandler. In our CustomRouteHandler we first check to see if the query string parameter is present (we do this with a simple regular expression on the URL query section). The OutputRouteDiagnostics method is shown in Listing 7. 
&lt;p&gt;&lt;strong&gt;Listing 7 – Rendering route diagnostics information to the response stream&lt;/strong&gt; &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OutputRouteDiagnostics(RouteData routeData, HttpContextBase context) 
{ 
    var response = context.Response; 
    response.Write( 
        &lt;span class="str"&gt;@"&amp;lt;style&amp;gt;body {font-family: Arial;} 
                         table th {background-color: #359; color: #fff;} 
             &amp;lt;/style&amp;gt; 
             &amp;lt;h1&amp;gt;Route Data:&amp;lt;/h1&amp;gt; 
             &amp;lt;table border='1' cellspacing='0' cellpadding='3'&amp;gt; 
                  &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Key&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Value&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;"&lt;/span&gt;); &lt;strong&gt;#1&lt;/strong&gt; 
    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var pair &lt;span class="kwrd"&gt;in&lt;/span&gt; routeData.Values) 
    { 
          response.Write(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;{0}&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;{1}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;"&lt;/span&gt;, 
              pair.Key, pair.Value)); 
    } 

    response.Write(&lt;span class="str"&gt;@"&amp;lt;/table&amp;gt; 
           &amp;lt;h1&amp;gt;Routes:&amp;lt;/h1&amp;gt; 
           &amp;lt;table border='1' cellspacing='0' cellpadding='3'&amp;gt; 
                   &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Route&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;"&lt;/span&gt;); &lt;strong&gt;#2&lt;/strong&gt; 
    &lt;span class="kwrd"&gt;bool&lt;/span&gt; foundRouteUsed = &lt;span class="kwrd"&gt;false&lt;/span&gt;; 

    &lt;span class="kwrd"&gt;foreach&lt;/span&gt;(Route r &lt;span class="kwrd"&gt;in&lt;/span&gt; RouteTable.Routes) 
    { 
        response.Write(&lt;span class="str"&gt;"&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;"&lt;/span&gt;); 
        &lt;span class="kwrd"&gt;bool&lt;/span&gt; matches = r.GetRouteData(context) != &lt;span class="kwrd"&gt;null&lt;/span&gt;; 
        &lt;span class="kwrd"&gt;string&lt;/span&gt; backgroundColor = matches ? &lt;span class="str"&gt;"#bfb"&lt;/span&gt; : &lt;span class="str"&gt;"#fbb"&lt;/span&gt;; &lt;strong&gt;#3&lt;/strong&gt; 
        &lt;span class="kwrd"&gt;if&lt;/span&gt;(matches &amp;amp;&amp;amp; !foundRouteUsed) 
        { 
            response.Write(&lt;span class="str"&gt;"&amp;amp;raquo;"&lt;/span&gt;); &lt;strong&gt;#4&lt;/strong&gt; 
            foundRouteUsed = &lt;span class="kwrd"&gt;true&lt;/span&gt;; 
        } 
        response.Write(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format( 
              &lt;span class="str"&gt;"&amp;lt;/td&amp;gt;&amp;lt;td style='font-family: Courier New; background-color:{0}'&amp;gt;{1}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;"&lt;/span&gt;, 
              backgroundColor, r.Url)); 
    } 

    response.End(); 
} &lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;&lt;em&gt;1. Create an HTML table to display the route values for the current request. &lt;br&gt;2. Create an HTML table to display the routes &lt;br&gt;3. Green if it matches, Red if it doesn't &lt;br&gt;4. Places a chevron character (») next to the route selected for the request &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This method outputs two tables, one for the current route data, and one for the routes in the system. Each route will return null for GetRouteData if the route doesn’t match the current request. The table is then colored to show which routes matched, and a little arrow indicates which route is the one in use for the current URL. The response is then ended to prevent any further rendering. 
&lt;p&gt;To finalize this change, we have to alter the current routes to use our new handler. 
&lt;p&gt;&lt;strong&gt;Listing 8 – Assigning routes to our custom route handler &lt;/strong&gt;&lt;pre class="csharpcode"&gt;RouteTable.Routes.Add( 
  &lt;span class="kwrd"&gt;new&lt;/span&gt; Route(&lt;span class="str"&gt;"{conferenceKey}/{action}"&lt;/span&gt;, 
  &lt;span class="kwrd"&gt;new&lt;/span&gt; RouteValueDictionary( &lt;span class="kwrd"&gt;new&lt;/span&gt; { Controller=&lt;span class="str"&gt;"Conference"&lt;/span&gt; }), 
  &lt;span class="kwrd"&gt;new&lt;/span&gt; CustomRouteHandler())); 

RouteTable.Routes.Add( 
  &lt;span class="kwrd"&gt;new&lt;/span&gt; Route(&lt;span class="str"&gt;"{controller}/{action}/{id}"&lt;/span&gt;, 
  &lt;span class="kwrd"&gt;new&lt;/span&gt; RouteValueDictionary( &lt;span class="kwrd"&gt;new&lt;/span&gt; { Action=&lt;span class="str"&gt;"Index"&lt;/span&gt;, id=(&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;span class="kwrd"&gt;null&lt;/span&gt; }), 
  &lt;span class="kwrd"&gt;new&lt;/span&gt; CustomRouteHandler())); 

&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;The end result (shown in Listing 2) is incredibly helpful. Let’s use the /home/index URL (that resulted in a 404 in Listing 1) but this time we’ll add the ?routeInfo to the query string. We can see in the route data table that the value “home” was picked up as a conference key, as shown in figure 2. The route table confirms that the conference key route was picked up first, since it matched. 
&lt;p&gt;&lt;img border="0" alt="clip_image009" src="http://flux88.com/files/media/image/WindowsLiveWriter/ExcerptfromASP.NETMVCinActionChapter6_ED7F/clip_image009_09a4468a-13c8-4b55-8ff9-41601fe8f767.jpg" width="569" height="480"&gt; 
&lt;p&gt;&lt;strong&gt;Listing 2 – appending ?routeInfo gives us detailed information about the current request’s route. We can easily see now that the wrong route was chosen. &lt;/strong&gt;
&lt;p&gt;Now you can immediately tell that the current route used is not the one we intended. We can also tell whether or not other routes match this request by the color of the cell: Both of the rows are green. We now quickly identify the issue as a routing problem and can fix it accordingly. In this case, if we add constraints to the first route such that conferenceKey isn’t the same as one of our controllers, the problem is resolved. Remember that order matters! The first route matched is the one used. 
&lt;p&gt;Of course you wouldn’t want this information to be visible in a deployed application, so only use to aid your development. You could also build a switch that changes the routes to the CustomRouteHandler if you’re in debug mode, which would be a more automated solution. I’ll leave this as an exercise for the reader. 
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Inspired by Phil Haack’s Route Debugger &lt;/strong&gt;
&lt;p&gt;This example was inspired by Phil Haack’s route debugger that he posted on his blog when the ASP.NET MVC Framework was in Preview 2. It is a great example of what you can do with the information provided to you by the routing system. You can see his original example of this here: 
&lt;p&gt;&lt;a href="http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx"&gt;http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx&lt;/a&gt;. &lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Another potential use of a custom route handler would be to append a specific identifier to the query string automatically. This could be useful in scenarios where you rely on cookie-less sessions or maybe you have a company identifier that limits what is displayed on the screen (your author has interfaced with such a framework). An IHttpHandler that would satisfy this requirement might look like this: 
&lt;p&gt;&lt;strong&gt;Listing 9 – An MvcHandler that can enforce query string parameters&lt;/strong&gt; &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; EnsureCompanyKeyHandler : MvcHandler 
{ 
  &lt;span class="kwrd"&gt;public&lt;/span&gt; EnsureCompanyKeyHandler(RequestContext requestContext) 
    : &lt;span class="kwrd"&gt;base&lt;/span&gt;(requestContext) 
  { 
  } 

  &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ProcessRequest(HttpContextBase context) 
  { 
    var controller = (&lt;span class="kwrd"&gt;string&lt;/span&gt;) RequestContext.RouteData.Values[&lt;span class="str"&gt;"controller"&lt;/span&gt;]; 
    var company = context.Request.QueryString[&lt;span class="str"&gt;"company"&lt;/span&gt;]; 
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (controller != &lt;span class="str"&gt;"login"&lt;/span&gt; &amp;amp;&amp;amp; company == &lt;span class="kwrd"&gt;null&lt;/span&gt;) 
    { 
      context.Response.Redirect(&lt;span class="str"&gt;"~/login"&lt;/span&gt;); &lt;strong&gt;#1&lt;/strong&gt; 
    } 
    &lt;span class="kwrd"&gt;else&lt;/span&gt;  
    { 
      &lt;span class="kwrd"&gt;base&lt;/span&gt;.ProcessRequest(context); &lt;strong&gt;#2&lt;/strong&gt; 
    } 
  } 
} &lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;&lt;em&gt;1. Force them to login &lt;br&gt;2. The URL contains a company key, so we can continue &lt;/em&gt;
&lt;p&gt;In this example, every request must have a company key. The ProcessRequest method will not continue unless the URL contains this. 
&lt;p&gt;Hopefully you noticed how easy it was to extend the framework. Since most of the objects that you interact with are either interfaces or abstract base classes, it allows you to completely (or almost completely) substitute behavior for your own. It is in this level of flexibility where you will see the ASP.NET MVC Framework really shine.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This article is taken from the book &lt;a href="http://manning.com/palermo/"&gt;ASP.NET MVC in Action&lt;/a&gt; from Manning Publications.&lt;/p&gt;&lt;/blockquote&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/flux88?a=ItWhzAmeFSE:GD07CJvz1i8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=ItWhzAmeFSE:GD07CJvz1i8:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/flux88?a=ItWhzAmeFSE:GD07CJvz1i8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/flux88?i=ItWhzAmeFSE:GD07CJvz1i8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><feedburner:origLink>http://flux88.com/blog/excerpt-from-asp-net-mvc-in-action-chapter-6/</feedburner:origLink></item></channel></rss>
