<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Rob's Blog</title>
        <link>http://robrich.org/Default.aspx</link>
        <description>Rob's Blog</description>
        <language>en-US</language>
        <copyright>Rob Richardson</copyright>
        <managingEditor>robrich@robrich.org</managingEditor>
        <generator>Subtext Version 2.0.0.43</generator>
        <image>
            <title>Rob's Blog</title>
            <url>http://robrich.org/images/RSS2Image.gif</url>
            <link>http://robrich.org/Default.aspx</link>
            <width>77</width>
            <height>60</height>
        </image>
        <item>
            <title>iPhone: it's not really a digital convergence device</title>
            <category>Rants</category>
            <link>http://robrich.org/archive/2010/03/04/iphone-its-not-really-a-digital-convergence-device.aspx</link>
            <description>It finally gelled in my head what bugged me about the iPhone's lack of simultaneous processing.  It's not truly a digital convergence device.  It's a sequential task device.&lt;br /&gt;
&lt;br /&gt;
A digital convergence device is a device that does lots of things: MP3/FM music player, alarm clock, cell phone, web browser, calendar, address book, GPS-enabled map, pedometer, etc.  The purpose of such a device is to do all of these things, not each of these things.  If I can't do them all simultaneously, it isn't a convergence device, it's a sequential device.  The iPhone is exactly that: a sequential task device.&lt;br /&gt;
&lt;br /&gt;
If I've decided I'm going to IM, I can't do anything else with the phone -- I can't browse the web, can't check on news feeds, can't check email.  The device is useless to me until I get an IM.  If I wanted an IM-only device, I'd have bought one.  I bought a digital convergence device.  The same could be said of any app that receives data: Skype, Google Voice, Email, RSS feeds, Facebook sync, texting services, RTMPGs, etc, as well as anything that monitors anything like Google Latitude, a pedometer app, navigation app, etc.  Anything I expect to alert me to something or to keep track of something either needs to "push notification" me, or I forfeit all other features of this device as I use it for that task.  If it goes the push notification route, the logic must be in the cloud, not on my device, can't be peer-to-peer, and can't get real-time status call-backs -- e.g. it can't auto-detect where I am and update my progress.  As an extreme example, I can't count the number of times I was playing some random game and walked around for a while looking for a clock so I didn't need to kill my game.  My convergence device was in "single task" mode.&lt;br /&gt;
&lt;br /&gt;
The notable exceptions to the single-use mode are all Apple apps: phone, iTunes, and alert apps such as calendar and text alerts.  I can get a call which immediately and irrevocably halts anything I'm doing (including upgrading OS versions), and I can listen to iTunes music while I do a few other things.  But what if my music player of choice is Pandora?&lt;br /&gt;
&lt;br /&gt;
I think you see where I'm going with this.  The iPhone clearly isn't a digital convergence device.  Neither is the iPad.  It is clearly a sequential task device, a data snacker device.  Pick the function you want it to do now, and it'll do great.  Want to do 2 things at once?  Well of course, buy two of them.  Want to get alerted when something happens?  Buy a specialty device too.  Um, I think I'll pass.&lt;img src="http://robrich.org/aggbug/63.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2010/03/04/iphone-its-not-really-a-digital-convergence-device.aspx</guid>
            <pubDate>Thu, 04 Mar 2010 18:32:12 GMT</pubDate>
            <wfw:comment>http://robrich.org/comments/63.aspx</wfw:comment>
            <comments>http://robrich.org/archive/2010/03/04/iphone-its-not-really-a-digital-convergence-device.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/63.aspx</wfw:commentRss>
        </item>
        <item>
            <title>iPhone: the rise and fall of the latest Apple gadget</title>
            <category>Rants</category>
            <link>http://robrich.org/archive/2010/02/19/iphone-the-rise-and-fall-of-the-latest-apple-gadget.aspx</link>
            <description>The iPhone.  It's a wonderful device.  It was a game changer.  3 years ago when it was released, it revolutionized the phone landscape.  For the first time, people had a portable digital convergence device.  (Ok, maybe it wasn't the first, maybe it wasn't the best, maybe it was just targeted at regular people instead of corporate users.)  For the first time, we could walk around with a web browser, a calendar, a music player, an address book, and really manage our lives on the go.  (Ok, I'll grant that BlackBerry defined that niche for business users, but the iPhone made it cool and made it work for consumers.)&lt;br /&gt;
&lt;br /&gt;
I'm hesitant to sit on the bleeding edge.  I waited until Service Pack 1 to get my iPhone 3G.  It was nearly 2 years ago.  It was a game changer for me too.  At random times in random places, I could check email, surf the web to answer the nagging question, create calendar entries, or just horse around.  I could pull up a map of where I am and where I wanted to go, so the preparation for travel wasn't as urgent.  I could schedule stuff on my calendar, so no more wads of post-its hoping I guessed right.  And reading email in the 2 minutes standing in line or on the walk home from dropping kids off at school is awesome.  It truly revolutionized my world for the better.&lt;br /&gt;
&lt;br /&gt;
Fast forward 3 years for Apple, nearly 2 years for me.  I waited with baited breath at every Apple announcement for the thing that'd keep the iPhone cool or for them to switch to a new carrier.  (The tag-line for the iPhone I've heard not a few times is, "The iPhone is so cool it almost makes up for being stuck on AT&amp;amp;T.")  In that time, they've started to back-fill some missing features, and made subtle improvements, but they've really never leaped out and grabbed me again.&lt;br /&gt;
&lt;br /&gt;
The following features were instantly missing from my experience, and with few exceptions, Apple really never delivered:&lt;br /&gt;
&lt;ul&gt;
    &lt;li&gt;OTA Syncing&lt;/li&gt;
    &lt;li&gt;contact and calendar categories&lt;/li&gt;
    &lt;li&gt;turn-by-turn voice navigation&lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;copy &amp;amp; paste&lt;/li&gt;
    &lt;li&gt;an IM and VOIP client that's always on (e.g. I'll still get new IMs or receive VOIP calls if I switched over to read my email)&lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;3rd party data on maps (e.g. "map all my contacts" or "where is the  closest gas station on my route" or "does Acme, Inc. have an office near  me?"  I &lt;a href="javascript:void(0);/*1266596507646*/"&gt;ranted&lt;/a&gt; about  this previously -- that I want to shove a kml file into maps.)&lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;OpenVPN / RDP client&lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;disable auto-rotation based on the accelerometer -- so I can read in bed&lt;/li&gt;
&lt;/ul&gt;
Ok, I'll grant that some of these things have come with third-party apps.  Some have come as jailbreak apps.  Some are just not there.&lt;br /&gt;
&lt;br /&gt;
And I get that I'm hardly a typical user.  Most users looking for "IM client" on a phone would point me at text messaging.  (Yeah, but I can't text into an MSN IM contact.  And if a Skype contact IMs me back but I'm sending an email, I never get it.  Yeah, I know Trillian Astra is "almost there".  I've been waiting on them for as long too.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Meanwhile, over the last 3 years since the iPhone changed the landscape, Android and most recently Windows Mobile 7 have come into view.  Neither is as polished as the iPhone was at launch.  (I've not seen a Win 7 phone, but I've seen a good deal of Android phones.)  Android only recently got pinch-to-zoom, and really only on Nexus One, and the Droid's map application.  But I see a lot more potential in these devices than in the iPhone.&lt;br /&gt;
&lt;br /&gt;
For instance, me and my family were on vacation in California.  We were caravaning with friends on an unfamiliar stretch of highway.  We popped open the Droid, put in our destination in the voice guidance app, and went back to the home screen.  When something of interest popped up in a friends' cars, they'd text us or tweet.  As the perfect example, my wife was on the web looking up something, the navigation was telling me where to turn, and a text came in.  It all happened simultaneously.  It just worked.&lt;br /&gt;
&lt;br /&gt;
I've played with the Droid pretty extensively since.  I can push the search button, and pull up a web page or a contact or directions.  The back button is just truly awesome -- getting me back a web page or back into the previous app or back a page in the app.   It just works.  The syncing is awesome because it just works.  I'm very good at forgetting day-to-day stuff, and so I often find I haven't sync'd my calendar in a while, and when I do, I double-booked myself.  There's no android sync procedure -- it just does it.&lt;br /&gt;
&lt;br /&gt;
And don't get me started on the iPhone carrier lock-in.  I probably would've gotten a 3GS if my carrier of choice was announced last July.  As it stands, I'm the only member of my circle of mobiles that can't use free mobile-to-mobile minutes ... because I'm stuck in AT&amp;amp;T -- say nothing of the service.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When Android finally got pinch-to-zoom, it was a done deal.  I'm sold.  As soon as my AT&amp;amp;T contract is up, I'm sailing away on Android.  It'll let me use it the way I want.&lt;br /&gt;
&lt;br /&gt;
Rob&lt;img src="http://robrich.org/aggbug/62.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2010/02/19/iphone-the-rise-and-fall-of-the-latest-apple-gadget.aspx</guid>
            <pubDate>Fri, 19 Feb 2010 17:02:15 GMT</pubDate>
            <wfw:comment>http://robrich.org/comments/62.aspx</wfw:comment>
            <comments>http://robrich.org/archive/2010/02/19/iphone-the-rise-and-fall-of-the-latest-apple-gadget.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/62.aspx</wfw:commentRss>
        </item>
        <item>
            <title>VS's Cassini (Web Server) + Fiddler = Remote testing</title>
            <category>Tools</category>
            <link>http://robrich.org/archive/2010/02/15/vss-cassini-web-server-fiddler-remote-testing.aspx</link>
            <description>From time to time, I have a need to debug a web site from a browser not installed on my current machine.  Safari/Mac or phone browsers are the quintessential example.  Granted, if it happens server-side, it happens for all browsers, and if it happens client-side, debugging server-side may not help.  But there's that one random time every now and again when this becomes quite important: debug server, client isn't on localhost.  Perhaps it's easier to replay the request from the browser where the problem happened rather than figure out how to simulate it locally.  Perhaps it's a weird combination of race conditions that make it happen.  Perhaps it's how the cookies built up that led to cruft not easily reproducible elsewhere.  Alas, being able to debug the server from a non-local client comes in mighty handy now-and-again.&lt;br /&gt;
&lt;br /&gt;
As we all know, Visual Studio's built in web server (originally based on Cassini) is hard-coded to only bind to loopback.  If I had my way that wouldn't be the case, but here we are.  Traditionally, we'd need to install our site in IIS, attach to the w3svc service, and debug that way.  (Even if you're not on a 64-bit box, you can empathize with how intense that is.)&lt;br /&gt;
&lt;br /&gt;
Fiddler is an awesome tool for watching network traffic flow between browser and web server.  In the end, everything you send between server and browser is either HTML, CSS, or JavaScript (or binary content like images and plug-ins), so watching it happen is incredibly insiteful.  We'll not use Fiddler for that here, but I highly recommend it for that work as well.  (There's times when watching the traffic yields insights quite difficult to see any other way.)  Alas, today we'll just mis-use it as a proxy server that can forward traffic back and forth from a LAN address to a loopback address.&lt;br /&gt;
&lt;br /&gt;
Here's the steps:&lt;br /&gt;
&lt;br /&gt;
1. Download and install Fiddler from &lt;a rel="nofollow" href="www.fiddlertool.com"&gt;www.fiddlertool.com&lt;/a&gt; on the same machine as Visual Studio.&lt;br /&gt;
&lt;br /&gt;
2. Tools menu -&amp;gt; Fiddler Options -&amp;gt; Connections tab: click on "Allow remote computers to connect", and push ok.  (While I'm in here, I usually turn off IPv6 in the General tab as that's another no-no in VS's version of Cassini.)&lt;br /&gt;
&lt;br /&gt;
3.  Rules menu -&amp;gt; Customize Rules.  For me, it opened up CustomRules.js in notepad.&lt;br /&gt;
&lt;br /&gt;
4. Scroll down to the function labeled &lt;span style="font-family: Courier New;"&gt;OnBeforeRequest &lt;/span&gt;and add a line kinda like this:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;if (oSession.host.toLowerCase() == "192.168.1.5:8888") oSession.host = "localhost:45678";&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Replace the first IP with the address of your machine (ipconfig /all from a cmd will give you this), and replace the port at the end with what ever you set / VS assigned to your project.  (Inside Visual Studio, in the project properties window, in the web tab, I always set it to "Specific Port" so I don't have to come in here and futz with it every time VS wants to "help".)&lt;br /&gt;
&lt;br /&gt;
This line says "if the inbound request says it's going to this ip and port (that fiddler is listening to), reroute it to this other ip and port (that Visual Studio's web debugger is listening to).&lt;br /&gt;
&lt;br /&gt;
5. Scroll down a bit further in CustomRules.js to the &lt;span style="font-family: Courier New;"&gt;OnBeforeResponse &lt;/span&gt;function and add a line kinda like this:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;oSession.utilReplaceInResponse("localhost:45678","192.168.1.5:8888");&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
You'll also need to change the IP and port here to match the changes above as well, but note they're reversed.&lt;br /&gt;
&lt;br /&gt;
This line says "if the body of the outbound message includes text that routes to Visual Studio's debugger, rewrite it to point to Fiddler."&lt;br /&gt;
&lt;br /&gt;
6. Save this file, restart Fiddler, and try it out.&lt;br /&gt;
&lt;br /&gt;
(You may also have to adjust firewall rules on your development machine to allow inbound TCP connections on port 8888.)&lt;br /&gt;
&lt;br /&gt;
And that's it!  Now you're remote debugging your project from a non-local address.&lt;br /&gt;
&lt;br /&gt;
One final note: ideally, we'd create another rule in &lt;span style="font-family: Courier New;"&gt;OnBeforeResponse &lt;/span&gt;that would rewrite headers as well.  I haven't been very successful in doing that, so I haven't included all the ways that don't work.  But if you're sending back a redirect to a full url without this rule, your client will happily time out looking for content on itself.  Why itself?  Because you redirected to localhost.  :D&lt;br /&gt;
&lt;br /&gt;
Rob&lt;img src="http://robrich.org/aggbug/61.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2010/02/15/vss-cassini-web-server-fiddler-remote-testing.aspx</guid>
            <pubDate>Mon, 15 Feb 2010 18:25:58 GMT</pubDate>
            <wfw:comment>http://robrich.org/comments/61.aspx</wfw:comment>
            <comments>http://robrich.org/archive/2010/02/15/vss-cassini-web-server-fiddler-remote-testing.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/61.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Logging and Rewriting Service Calls</title>
            <category>Code</category>
            <link>http://robrich.org/archive/2010/02/15/logging-and-rewriting-service-calls.aspx</link>
            <description>I love web services.  I love how easy it is to wire up a JavaScript client either through jQuery or through a ServiceProxy.  I love how I can point a .net client at a service, and I get strongly typed command parameters.  And my latest love of asmx services in C# is the SoapExtension.  A SoapExtension is a class that allows you to inspect outgoing or incoming services to get at the data involved.  I use them for logging service calls (frequency, duration, errors), and for rewriting output (fixed a "double html encoded" bug, remove whitespace, rewrite SoapFaults, etc).&lt;br /&gt;
&lt;br /&gt;
The technique is incredibly awesome, and I can't claim original ownership, but I can claim excellent results.  A few simple steps:&lt;br /&gt;
&lt;br /&gt;
1. Create a class that derives from SoapExtension.&lt;br /&gt;
&lt;br /&gt;
2. Override ProcessMessage, handling the SoapMessage's Stage that you're interested in.&lt;br /&gt;
&lt;br /&gt;
3. Add either a web.config entry (to handle all inbound and outbound service calls), or put an attribute on each WebMethod you want to track.&lt;br /&gt;
&lt;br /&gt;
Voila!  You've got a soap extension.&lt;br /&gt;
&lt;br /&gt;
Here's my ExampleSoapExtension (business logic replaced with TODO to keep it simple):&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;namespace ExampleNamespace {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     #region using&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     using System;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     using System.Data.Linq;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     using System.IO;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     using System.Linq;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     using System.Text.RegularExpressions;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     using System.Threading;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     using System.Web;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     using System.Web.Services.Protocols;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     #endregion&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     public class ExampleSoapExtension : SoapExtension {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         private Stream originalStream; // The original stream&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         private Stream internalStream; // Our new stream we chained into place&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         public ExampleSoapExtension() {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         // Called the first time the Web service is used if configured with a config file&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         public override object GetInitializer( Type t ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             return typeof( ExampleSoapExtension );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         // Called the first time the Web service is used if configured with an attribute&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         public override object GetInitializer( LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             return attribute;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         // Called each time the Web service is used and gets passed the data from GetInitializer() method&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         public override void Initialize( object initializer ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // Get the attribute here and pull whatever you need off it.&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             //ExampleSoapExtensionAttribute attr = initializer as ExampleSoapExtensionAttribute;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         // The ChainStream() method gives us a chance to grab the SOAP messages as they go by&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         public override Stream ChainStream( Stream stream ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // Save the original stream&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             originalStream = stream;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // Create and return our own in its place&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             internalStream = new MemoryStream();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             return internalStream;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         // The ProcessMessage() method is called between each step in the server-side process&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         public override void ProcessMessage( SoapMessage message ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             switch ( message.Stage ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 case SoapMessageStage.BeforeDeserialize:&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     // About to handle incoming SOAP request&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     string requestContent = StreamToText( this.originalStream, false );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     WriteIncomingToLog( message, requestContent );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     TextToStream( requestContent, this.internalStream, true );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     break;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 case SoapMessageStage.AfterDeserialize:&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     // incoming SOAP request has been deserialized&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     WriteInputToLog( message );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     break;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 case SoapMessageStage.BeforeSerialize:&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     // About to prepare outgoing SOAP Response&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     WriteOutputToLog( message );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     break;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 case SoapMessageStage.AfterSerialize:&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     // outgoing SOAP response is ready to go&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     string responseContent = null;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     if ( message.Exception != null ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                         // Rewrite soap fault as valid soap message with internal error code&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                         // Though it might be nice to do this before serialization, we can't inject our own return value easily&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                         responseContent = RewriteError( message );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     } else {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                         responseContent = StreamToText( this.internalStream, true );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     WriteOutgoingToLog( message, responseContent );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     TextToStream( responseContent, this.originalStream, false );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     break;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 default:&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     throw new Exception( "invalid stage" );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         private static string StreamToText( Stream stream, bool rewindBefore ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if ( rewindBefore ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 stream.Position = 0;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             TextReader reader = new StreamReader( stream );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             string content = reader.ReadToEnd();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             return content;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         private static void TextToStream( String text, Stream stream, bool rewindAfter ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             TextWriter writer = new StreamWriter( stream );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             writer.Write( text );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             writer.Flush();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if ( rewindAfter ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 stream.Position = 0;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         #region WriteIncomingToLog&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// Write the incoming stream content to the logs&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         private void WriteIncomingToLog( SoapMessage Message, string Content ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             HttpRequest req = HttpContext.Current.Request;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // TODO: Log various parameters here including the incoming xml and start date&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         #endregion&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         #region WriteInputToLog&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         private void WriteInputToLog( SoapMessage Message ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             ServiceInputObject input = null;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if ( Message.MethodInfo.InParameters.Length &amp;gt; 0 ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 try {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     input = Message.GetInParameterValue( 0 ) as ServiceInputObject;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 } catch ( Exception /*ex*/ ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                     input = null;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if ( input != null ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 // TODO: Log the message details&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         #endregion&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         #region WriteOutputToLog&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         private void WriteOutputToLog( SoapMessage Message ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if ( Message.Exception != null ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 // The return object doesn't exist because an exception was thrown&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 // RewriteError will create one&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 return;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             ServiceOutputObject output = null;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if ( Message.MethodInfo != null &amp;amp;&amp;amp; Message.MethodInfo.ReturnType != null &amp;amp;&amp;amp; Message.MethodInfo.ReturnType.FullName != "System.Void" ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 output = Message.GetReturnValue() as ServiceOutputObject;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             } else {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 output = null;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             if ( output != null ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 // TODO: Log the output details&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         #endregion&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         #region WriteOutgoingToLog&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// Write the message in the stream to the log4net log&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         private void WriteOutgoingToLog( SoapMessage Message, string Content ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             string outboundData = GetStreamText( StreamToLog );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // TODO: Log the outgoing xml string and end date&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         #endregion&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         #region CaptureError&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// Insure the exception is logged&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         /// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         private Stream CaptureError( SoapMessage Message, Stream stream ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // Log the exception&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             Exception ex = Message.Exception;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             while ( ex != null &amp;amp;&amp;amp; ex.InnerException != null &amp;amp;&amp;amp; ex.GetType() == typeof( SoapException ) ) {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;                 ex = ex.InnerException;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // TODO: Log the exception&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             &lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // TODO: Form the output reply and serialize it&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             string soapMessage = null;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // Now send this as the out stream instead of the &amp;lt;soap:Fault&amp;gt; stream we had before&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             MemoryStream outStream = new MemoryStream();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             TextWriter writer = new StreamWriter( outStream );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             writer.WriteLine( soapMessage );&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             writer.Flush();&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             outStream.Position = 0;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // And send the 200 status instead of 400&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             //HttpContext.Current.Response.StatusCode = 200;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             // Here's the content to send instead of what ever you had&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             return outStream;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         #endregion&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     [AttributeUsage( AttributeTargets.Method )]&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     public class ExampleSoapExtensionAttribute : SoapExtensionAttribute {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         public ExampleSoapExtensionAttribute() {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             this.Priority = 1;&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         public override int Priority { get; set; }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         // Specifies the class of the SOAP Extension to use with this method&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         public override Type ExtensionType {&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;             get { return typeof( ExampleSoapExtension ); }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;         }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;     }&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt; }&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
My current quest: how do I do this in WCF?  Is there such a thing as a "message watcher" or "handler" or "pipeline interceptor"?  All these terms on Google come up blank.  With WCF's new configuration-less services and MS's desire to move on past asmx, WCF seems a foregone conclusion.  For me, this is the last hurdle.&lt;br /&gt;
&lt;br /&gt;
Rob&lt;img src="http://robrich.org/aggbug/60.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2010/02/15/logging-and-rewriting-service-calls.aspx</guid>
            <pubDate>Mon, 15 Feb 2010 17:42:51 GMT</pubDate>
            <wfw:comment>http://robrich.org/comments/60.aspx</wfw:comment>
            <comments>http://robrich.org/archive/2010/02/15/logging-and-rewriting-service-calls.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/60.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Desert Code Camp and Desert Code Camp Jr</title>
            <category>Events</category>
            <link>http://robrich.org/archive/2009/10/31/desert-code-camp-and-desert-code-camp-jr.aspx</link>
            <description>In the past few years, I've been privileged to learn and network at Desert Code Camp.  When I jumped the fence to teach, it was an honor to learn from y'all as I shared the skills you'd taught me previously.  Many years ago, I began by teaching an intro to CSS and a team-taught SVN class.  Last code camp, I taught Thinking in JavaScript, Intro to jQuery, and Advanced jQuery including building plugins and animations.  I also got to learn about ASP.NET MVC, programming usb gadgets, and unit testing JavaScript -- to name a few.  It was a blast.&lt;br /&gt;
&lt;br /&gt;
For anyone who's not taught the skills and talents you have, take the opportunity to do so.  It is well worth the effort and the skills you develop are invaluable.  Imagine how confident you'll be in the next job interview when you notice the same stage fright that quickly passes when teaching a room full of peers can also dissipate just as fast when you're getting grilled by a potential colleague.  And imagine the awesome resume tick and skill justification when you can document that not only do you have x years doing it, but that you taught it to a crowded room of your peers.&lt;br /&gt;
&lt;br /&gt;
But I digress.  This year I'm taking a different path with Desert Code Camp.  My son often comes with me to Users' Group meetings -- mostly for the 1-on-1 time with me as we drive and the free pizza and stickers.  (At the conclusion of an evening 6 months or so ago, with his collection of treasured swag in hand, he said to me, "Dad, there's a lot of stickers in programming."  :D)  Each of the recruiters also engage him a bit each time, and I'm sure if he played his hand right, he could find an awesome job in 5 or 10 years.  Today, he does pretty well in DreamWeaver if I jump in with hard stuff and "how do you spell ...?" from time to time.  His site is &lt;a href="javascript:void(0);/*1257008703946*/"&gt;robrich.org/mark.html&lt;/a&gt;.  He created the concept when he was 4 as a way to keep track of his favorite sites without the need to ask me where the letter H was on his keyboard every time.  For a 4-year-old, the problem's solution was brilliant!  Lately he's been asking to learn more about the guts of how it works -- hardware, software, marketing, and finance.  An eager mind like his is such a treasure.&lt;br /&gt;
&lt;br /&gt;
Thus, this year, I'm not attending Desert Code Camp as a learning and teaching and networking opportunity.  This year, it will all be about my son.  &lt;a href="javascript:void(0);/*1257009449835*/"&gt;Desert Code Camp Jr&lt;/a&gt; is a trek slated for kids "ages 4 to 18".  (In my opinion, kids over  13 or 15 or so will probably want to take -- &lt;a href="javascript:void(0);/*1257009414331*/"&gt;or teach&lt;/a&gt; -- the other classes though.)  We'll learn about MIT's Scratch -- drag-drop programming for kids, programming Lego Mindstorms, and we'll learn about circuits.  Lunch is generously provided by GangPlank.  Mark explained to me he wants to give me some time to go to a grown-up class too, though I'll defer to him once the excitement kicks in.  The way they've structured it with a small instruction period up front and then a generous experimentation and play time afterward for each topic will be perfect for developing skill and creativity in these bright young minds.&lt;br /&gt;
&lt;br /&gt;
Thus, if you were looking for the Continuous Integration class or the Unit Testing with TypeMock and Ivonna class I hyped, or an encore performance of the Advanced jQuery class, you'll have to wait until next year.  This year, I get to be Dad -- the greatest honor I could imagine.&lt;br /&gt;
&lt;br /&gt;
Rob&lt;img src="http://robrich.org/aggbug/59.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2009/10/31/desert-code-camp-and-desert-code-camp-jr.aspx</guid>
            <pubDate>Sat, 31 Oct 2009 17:39:13 GMT</pubDate>
            <wfw:comment>http://robrich.org/comments/59.aspx</wfw:comment>
            <comments>http://robrich.org/archive/2009/10/31/desert-code-camp-and-desert-code-camp-jr.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/59.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Continuous Integration</title>
            <category>Tools</category>
            <category>Events</category>
            <link>http://robrich.org/archive/2009/09/24/continuous-integration.aspx</link>
            <description>It's my pleasure tonight to present Continuous Integration: best practices, methodologies, and tools at the SEVDNUG.  Continuous Integration is the process of rebuilding the code in its entirety periodically and automating awkward deployment processes to create a more consistent product.  Tonight we discussed these business cases, the tools and techniques available, and best practices to use when implementing a continuous integration process.&lt;br /&gt;
&lt;br /&gt;
It isn't difficult to get an automated build going.  Really the most difficult part is getting a one-line command to build it.  Be it batch files, calling Visual Studio's command line, or NAnt or MSBuild tasks, once you've got a command-line build, rigging it to a Continuous Integration service like CruiseControl.NET is easy.  Once you can automate this code verification, you'll immediately see benefits in decreased time chasing what broken and who broke it.&lt;br /&gt;
&lt;br /&gt;
The slides and code are available &lt;a href="http://robrich.org/content/ContinuousIntegration.zip"&gt;here&lt;/a&gt;. CruiseControl.NET is available &lt;a target="_blank" href="http://confluence.public.thoughtworks.org/"&gt;here&lt;/a&gt;, NAnt is available &lt;a target="_blank" href="http://nant.sourceforge.net/"&gt;here&lt;/a&gt;, and NAntContrib is available &lt;a target="_blank" href="http://nantcontrib.sourceforge.net/"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
** NOTE: For some strange reason, my server wants to gzip zip files when it downloads them, leading to a double-compressed file. If you're downloading the zip files in IE, it'll tell you the file is corrupt. The fault is totally mine, but &lt;span style="font-weight: bold;"&gt;the file is not corrupt&lt;/span&gt;. If you download the file with FireFox, it will come down just fine. If you're an IIS guru and know how to disable gzipping zipped content while enabling gzipping for non-zipped content, please let me know. **&lt;img src="http://robrich.org/aggbug/58.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2009/09/24/continuous-integration.aspx</guid>
            <pubDate>Thu, 24 Sep 2009 23:40:51 GMT</pubDate>
            <wfw:comment>http://robrich.org/comments/58.aspx</wfw:comment>
            <comments>http://robrich.org/archive/2009/09/24/continuous-integration.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/58.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Testing: Methodologies, Best Practices, and Tools</title>
            <category>Code</category>
            <category>Events</category>
            <link>http://robrich.org/archive/2009/08/28/testing-methodologies-best-practices-and-tools.aspx</link>
            <description>I had the privilege to speak at the &lt;a href="http://www.sevdnug.org/" tareget="_blank"&gt;SEVDNUG&lt;/a&gt; yesterday about Testing. When we typically think of "Testing", we usually use the term "Unit Testing", yet we usually mean "Integration Testing" or "Functional Testing". This was definitely not a demo on how to use NUnit, but rather a specific look at the reasons for testing, the best practices for writing tests, and a look at popular and obscure tools to facilitate the task.&lt;br /&gt;
&lt;br /&gt;
During the presentation, we looked at many tools: NUnit, TestDriven.NET, Resharper's test runner, TypeMock, Selenium, Ivonna, NUnit's &lt;span style="text-decoration: line-through;"&gt;RowTest &lt;/span&gt;TestCase (I still think 'RowTest' is more descriptive than 'TestCase', and I'm still annoyed I had to update all my code when I switched to NUnit 2.5. Find/Replace is a wonderful tool though.)&lt;br /&gt;
&lt;br /&gt;
One of the coolest things is that the goal of writing tests is so you spend less time debugging. Quite honestly, I'd rather write code than debug code any day. The key though is knowing what to test. Testing the .net framework or your database connection string is probably not the wisest use of your time. Testing that your business logic works the way you think it does is definitely a good way to keep bugs out of your code. To the depth that you can make the testing process seamless in your development, it can become an invaluable tool. Testing is an up-front investment that yields a long-tail benefit in improved code quality. If you can afford the investment, it's well worth it.&lt;br /&gt;
&lt;br /&gt;
One of the coolest points that came out during the discussion was using your suite of tests as documentation, new developer training, etc.  If your tests are run frequently and encompass the bulk of your code,  that's where the best definitions of your business logic reside. What an awesome idea.&lt;br /&gt;
&lt;br /&gt;
The slides and code are available &lt;a href="http://robrich.org/content/TestingDemo.zip"&gt;here&lt;/a&gt;.  If you're going to use the TypeMock and Ivonna content, you'll need to download trial licenses from &lt;a href="http://www.typemock.com/Downloads.php" target="_blank"&gt;here&lt;/a&gt;. All the other tools we discussed are open-source or free.&lt;br /&gt;
&lt;br /&gt;
** NOTE: For some strange reason, my server wants to gzip zip files when it downloads them, leading to a double-compressed file. If you're downloading the zip files in IE, it'll tell you the file is corrupt. The fault is totally mine, but &lt;span style="font-weight: bold;"&gt;the file is not corrupt&lt;/span&gt;. If you download the file with FireFox, it will come down just fine. If you're an IIS guru and know how to disable gzipping zipped content while enabling gzipping for non-zipped content, please let me know. **&lt;img src="http://robrich.org/aggbug/57.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2009/08/28/testing-methodologies-best-practices-and-tools.aspx</guid>
            <pubDate>Fri, 28 Aug 2009 17:13:16 GMT</pubDate>
            <wfw:comment>http://robrich.org/comments/57.aspx</wfw:comment>
            <comments>http://robrich.org/archive/2009/08/28/testing-methodologies-best-practices-and-tools.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/57.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Desert Code Camp Sessions</title>
            <category>Events</category>
            <link>http://robrich.org/archive/2009/06/14/desert-code-camp-sessions.aspx</link>
            <description>Yesterday we had an awesome time at Desert Code Camp learning from each other and sharing ideas with each other.  I got to present 3 sessions during the day, and here are the slides to each:&lt;br /&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://robrich.org/content/desertcodecamp_6-2009/Thinking_in_JavaScript.zip"&gt;Thinking in JavaScript&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://robrich.org/content/desertcodecamp_6-2009/jQuery_Intro.zip"&gt;Intro to jQuery&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://robrich.org/content/desertcodecamp_6-2009/jQuery_Deep_Dive.zip"&gt;jQuery Deep Dive&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
** NOTE: For some strange reason, my server wants to gzip zip files when it downloads them, leading to a double-compressed file.  If you're downloading the zip files in IE, it'll tell you the file is corrupt.  The fault is totally mine, but &lt;span style="font-weight: bold;"&gt;the file is not corrupt&lt;/span&gt;.  If you download the file with FireFox, it will come down just fine.  Since you'll need FireFox to use FireBug, you'll be just fine.  **&lt;br /&gt;
&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;Thinking in JavaScript&lt;/span&gt;: This is an awesome introduction to what makes JavaScript different from other C-Style languages such as C#, Java, C/C++, Perl, etc.  There are a few differences you need to understand, and with those in mind, you can leverage your existing skills in this new world with ease.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;Intro to jQuery&lt;/span&gt;: In this session, we look at the most common use of jQuery -- picking something, then doing something with each item selected.  For example: &lt;span style="font-family: Courier New;"&gt;$("p").css("background-color","#cccccc");&lt;/span&gt;  In that single line, we're able to search through the entire dom for all &lt;span style="font-family: Courier New;"&gt;&amp;lt;p&amp;gt;&lt;/span&gt; tags, and set their &lt;span style="font-family: Courier New;"&gt;background-color&lt;/span&gt; to gray.  1 line.  That's awesome.  We also briefly summarize some of the other stuff you get for your &lt;del&gt;26k&lt;/del&gt; now only 19k library script inclusion: AJAX, Animation, Traversing and modifying the dom, etc.&lt;br /&gt;
&lt;br /&gt;
jQuery Deep Dive: Here we briefly reviewed the "pick something, then do something with each" techniques.  Then we dive right in with AJAX: using GET and POST to retrieve content, sending parameters in the query string or as post parameters, techniques to call ASP.NET AJAX web services and page methods -- without a ScriptManager on the page, built-in jQuery animation, how use and build plugins, and how to interact with server-side controls and page life cycle.  By the time we were done with all that, we were definitely ready for lunch.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.desertcodecamp.com/" target="_blank"&gt;Desert Code Camp&lt;/a&gt; is a great opportunity for coders of all skill levels and all technology backgrounds to share and learn.  I thank you for the opportunity to learn with you.  See you at the next Desert Code Camp.&lt;img src="http://robrich.org/aggbug/56.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2009/06/14/desert-code-camp-sessions.aspx</guid>
            <pubDate>Sun, 14 Jun 2009 15:01:26 GMT</pubDate>
            <wfw:comment>http://robrich.org/comments/56.aspx</wfw:comment>
            <comments>http://robrich.org/archive/2009/06/14/desert-code-camp-sessions.aspx#feedback</comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/56.aspx</wfw:commentRss>
        </item>
        <item>
            <title>"Command Prompt" in Windows Explorer Context Menu</title>
            <category>Tools</category>
            <link>http://robrich.org/archive/2009/05/14/command-prompt-in-windows-explorer-context-menu.aspx</link>
            <description>There's a great power-toy for adding "Command Prompt" to the Windows     Explorer context menu in XP &lt;a href="http://www.microsoft.com/windowsxp/Downloads/powertoys/Xppowertoys.mspx" rel="nofollow"&gt;here&lt;/a&gt; (or search for XP Power Toys).  In Vista and Server 2008, you just hold shift when you right click to get it -- built in.  But what if you're on Windows Server 2003 or another version?  Well, the technique to add it is just a simple registry change:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-left: 40px;"&gt;&lt;span style="font-family: Courier New;"&gt; Windows Registry Editor Version 5.00&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New;"&gt;[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\Command_Prompt]&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;@="Command Prompt"&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\Command_Prompt\command]&lt;/span&gt;&lt;br style="font-family: Courier New;" /&gt;
&lt;span style="font-family: Courier New;"&gt;@="cmd.exe /k pushd \"%1\""&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
Copy the above into a reg file (such as "Command Prompt Here.reg" -- no quotes) or similar, double-click to merge it, and you've got a Command Prompt selection in Windows Explorer's context menu.  Easy as pie.  If you want to "uninstall" it, open up RegEdit, navigate to that key, and delete it.  Changes take effect imediately.&lt;br /&gt;
&lt;br /&gt;
Note: some have reported this syntax brings up an error.  If cmd.exe isn't in the PATH, this will utterly fail.  In some cases I've had success with changing the command to be &lt;span style="font-family: Courier New;"&gt;@="cmd.exe \"%1\""&lt;/span&gt;.  In some cases, that utterly fails too.  Your mileage may vary, batteries not included, don't use this product while sleeping on a curling iron or driving in traffic.&lt;br /&gt;
&lt;br /&gt;
And to take it a step further, I modified the command name to &lt;span style="font-family: Courier New;"&gt;"Command Prompt x86"&lt;/span&gt; and the command to &lt;span style="font-family: Courier New;"&gt;"C:\Windows\SysWoW64\cmd.exe \"%1\""&lt;/span&gt; and imported into a new key name, and I now have a 32-bit command prompt in the pop-up too.&lt;br /&gt;
&lt;br /&gt;
(Now hopefully I won't forget it again.)&lt;img src="http://robrich.org/aggbug/55.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2009/05/14/command-prompt-in-windows-explorer-context-menu.aspx</guid>
            <pubDate>Thu, 14 May 2009 19:02:42 GMT</pubDate>
            <wfw:comment>http://robrich.org/comments/55.aspx</wfw:comment>
            <comments>http://robrich.org/archive/2009/05/14/command-prompt-in-windows-explorer-context-menu.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/55.aspx</wfw:commentRss>
        </item>
        <item>
            <title>jQuery demo at SEVDNUG</title>
            <category>Code</category>
            <category>Events</category>
            <link>http://robrich.org/archive/2009/04/23/jquery-demo-at-sevdnug.aspx</link>
            <description>It was a blast to present deeper concepts of jQuery at the SEVDNUG this evening.  We enjoyed discussing ajax in jQuery, calling web services and page methods, building and using plugins, animation, and general best practices for JavaScript.  The content from the demo can be found &lt;a href="http://robrich.org/content/jquery.zip"&gt;here&lt;/a&gt;.  Note that because of a server misconfiguration, the file will come down double-zipped.  Firefox seems to download the file just fine, while IE seems to choke every time.&lt;br /&gt;
&lt;br /&gt;
For quick reference as well, here's the contents of the Resources page:&lt;br /&gt;
&lt;h2&gt;Tools&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;FireBug &lt;a href="http://www.getfirebug.com" target="_blank"&gt;http://www.getfirebug.com&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;YSlow &lt;a href="http://developer.yahoo.com/yslow/" target="_blank"&gt;http://developer.yahoo.com/yslow/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;jQuery intellisense in Visual Studio 2008:
    &lt;ul&gt;
        &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2008/11/21/jquery-intellisense-in-vs-2008.aspx" target="_blank"&gt;http://weblogs.asp.net/scottgu/archive/2008/11/21/jquery-intellisense-in-vs-2008.aspx&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href="http://blogs.msdn.com/webdevtools/archive/2008/10/28/rich-intellisense-for-jquery.aspx" target="_blank"&gt;http://blogs.msdn.com/webdevtools/archive/2008/10/28/rich-intellisense-for-jquery.aspx&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;JSLint &lt;a href="http://www.jslint.com" target="_blank"&gt;http://www.jslint.com&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;JavaScript Compressors:
    &lt;ul&gt;
        &lt;li&gt;Packer &lt;a href="http://dean.edwards.name/packer/" target="_blank"&gt;http://dean.edwards.name/packer/&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;JSMin &lt;a href="http://crockford.com/javascript/jsmin" target="_blank"&gt;http://crockford.com/javascript/jsmin&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Learning and Reference Material&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;Visual jQuery &lt;a href="http://www.visualjquery.com" target="_blank"&gt;http://www.visualjquery.com&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;jQuery API &lt;a href="http://api.jquery.com/" target="_blank"&gt;http://api.jquery.com/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;15 days of jQuery tutorials &lt;a href="http://15daysofjquery.com" target="_blank"&gt;http://15daysofjquery.com&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Google Tech Talk Dmitri Gaskin jQuery video &lt;a href="http://www.youtube.com/watch?v=8mwKq7_JlS8" target="_blank"&gt;http://www.youtube.com/watch?v=8mwKq7_JlS8&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Yahoo JavaScript Best Practices &lt;a href="http://developer.yahoo.com/performance/rules.html" target="_blank"&gt;http://developer.yahoo.com/performance/rules.html&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Contact Me &lt;a href="http://robrich.org" target="_blank"&gt;http://robrich.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;jQuery Plugins&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;jQuery plugin search &lt;a href="http://plugins.jquery.com/" target="_blank"&gt;http://plugins.jquery.com/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;jQuery UI demos &lt;a href="http://jqueryui.com/demos/" target="_blank"&gt;http://jqueryui.com/demos/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;7 of his favorite plugins &lt;a href="http://encosia.com/2008/10/19/7-of-my-favorite-jquery-plugins-for-use-with-aspnet/" target="_blank"&gt;http://encosia.com/2008/10/19/7-of-my-favorite-jquery-plugins-for-use-with-aspnet/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;ThickBox image gallery &lt;a href="http://jquery.com/demo/thickbox/" target="_blank"&gt;http://jquery.com/demo/thickbox/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Rounded corners &lt;a href="http://methvin.com/jquery/jq-corner-demo.html" target="_blank"&gt;http://methvin.com/jquery/jq-corner-demo.html&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;"Zebra Striped" table &lt;a href="http://15daysofjquery.com/examples/zebra/code/demoFinal.php" target="_blank"&gt;http://15daysofjquery.com/examples/zebra/code/demoFinal.php&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;BlockUI &lt;a href="http://malsup.com/jquery/block/#demos" target="_blank"&gt;http://malsup.com/jquery/block/#demos&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;jGrowl &lt;a href="http://stanlemon.net/projects/jgrowl.html" target="_blank"&gt;http://stanlemon.net/projects/jgrowl.html&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;jQuery validate &lt;a href="http://docs.jquery.com/Plugins/Validation/validate" target="_blank"&gt;http://docs.jquery.com/Plugins/Validation/validate&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Table Sorter &lt;a href="http://tablesorter.com/docs/" target="_blank"&gt;http://tablesorter.com/docs/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;jTemplate &lt;a href="http://plugins.jquery.com/project/jTemplates" target="_blank"&gt;http://plugins.jquery.com/project/jTemplates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;FAQ&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://encosia.com/2009/03/25/document-ready-and-pageload-are-not-the-same/" target="_blank"&gt;Why $(document).ready() and pageLoad() aren't the same&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://encosia.com/2008/06/05/3-mistakes-to-avoid-when-using-jquery-with-aspnet-ajax/" target="_blank"&gt;3 Mistakes to avoid when using jQuery with ASP.NET AJAX&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://encosia.com/2008/03/27/using-jquery-to-consume-aspnet-json-web-services/" target="_blank"&gt;Using jQuery to consume ASP.NET AJAX JSON Web Services&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://encosia.com/2008/05/29/using-jquery-to-directly-call-aspnet-ajax-page-methods/" target="_blank"&gt;Using jQuery to consume ASP.NET Page Methods&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://encosia.com/2009/03/04/use-jquery-to-catch-and-display-aspnet-ajax-service-errors/" target="_blank"&gt;AJAX Error handling with jQuery&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://dotnetslackers.com/columns/ajax/AspNetAjaxExceptionLogging.aspx" target="_blank"&gt;JavaScript Error Handling with an ASP.NET AJAX object (Kazi)&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://nettuts.com/tutorials/javascript-ajax/everything-you-need-to-know-about-jquery-13/" target="_blank"&gt;What's new in jQuery 1.3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://robrich.org/aggbug/54.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Rob Richardson</dc:creator>
            <guid>http://robrich.org/archive/2009/04/23/jquery-demo-at-sevdnug.aspx</guid>
            <pubDate>Fri, 24 Apr 2009 06:02:05 GMT</pubDate>
            <wfw:comment>http://robrich.org/comments/54.aspx</wfw:comment>
            <comments>http://robrich.org/archive/2009/04/23/jquery-demo-at-sevdnug.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://robrich.org/comments/commentRss/54.aspx</wfw:commentRss>
        </item>
    </channel>
</rss>