June 2005 Entries
In an effort to cut down on the bandwidth used by RSS feeds, Subtext implements the RFC3229 for feeds as proposed by Bob Wyman.
Unfortunately, FeedValidator.org now says my feed is not valid. The reason is that Feed Validator assumes that the HTTP Status code of 226 IM Used is an error. Perhaps it does not yet recognize RFC3229.
From the title of his post, Dream Hangovers, I thought Robb was going to tell some story about another night of too much drinking and the painful consequences afterwards. Instead he talks about how realistic dreams can often influence your mood the following day.
A few nights ago I had a dream in which I kept biting down on something hard. I spat the foreign object into my hand and was surprised to find a molar. For some reason, losing my teeth is a typical nightmare for me when I’m anxious. However this time, it was much more intense than before.
After spitting out a few teeth, I noticed I was biting on something much larger that felt like a rock or a piece of plaster. I spit it out and it my hand was a gleaming pale chunk of my jaw. Another chunk came out and I rushed to the bathroom to look in the mirror. When I opened my mouth, my entire lower jaw caved in and blood started filled up my mouth and pouring into the sink along with white pieces of my jaw. It reminded me of a river full of floating icebergs. That’s when I woke up in a cold sweat breathing very hard, furtively checking all my teeth with my tongue.
After a few moments of abject terror, I calmed down and thanked my lucky stars that all my teeth were there.
You kind of get the feeling that Keith Brown has a beef with soap exceptions when he writes that SoapException Sucks. I won’t rehash everything he says here, but the gist of his complaint is that when throwing an exception from within a web service, the exception gets wrapped by a SoapException. What’s so bad about that? As Keith relates, the Message property of the SoapException class intersperses your fault string with a load of other crap you really don’t care about. Also, the InnerException doesn’t get serialized into the SOAP fault packet, so it is always null on the client side.
A couple solutions proposed within his comments require putting a try/catch around the body of every method and construct a suitable SoapException by hand. This just didn’t sit well with me (neither did the burrito I just ate) as it seemed quite repetitive. I figured there had to be a better way. If only there were some way to inject code after a SOAP method is called and before the XML payload is delivered to the client. Fortunately there is. SOAP Extensions!
The solution I hacked together here is to build a custom SoapExtensionAttribute used to mark up a method. If that method throws an exception, the original exception information is serialized into the detail element of the soap exception.
The key here is to remember that SOAP is at its core simply XML text messages being sent back and forth between computers. A SoapExtension lets you peek under the hood and manipulate the actual messages going in and out.
There are three classes involved in this solution, SerializedExceptionExtensionAttribute, SerializedExceptionExtension and SoapOriginalException. I’ll briefly go over each one.
SerializedExceptionExtensionAttribute is a very simple Attribute class that inherits from SoapExtensionAttribute. When applied to a target, this attribute has a property that indicates what type of SoapExtension to use for that target.
SerializedExceptionExtension inherits from SoapExtension and for the most part looks like your typical MSDN example of a soap extension in which you override ChainStream, store the old stream in a member variable, and replace it with a new stream. For the sake of illustration, I will highlight a few methods that make this extension somewhat interesting (at least for me)...
public override void ProcessMessage(SoapMessage message)
{
if(message.Stage == SoapMessageStage.AfterSerialize)
{
_newStream.Position = 0;
if(message.Exception != null && message.Exception.InnerException != null)
{
InsertDetailIntoOldStream(message.Exception.InnerException);
}
else
{
CopyStream(_newStream, _oldStream);
}
}
else if(message.Stage == SoapMessageStage.BeforeDeserialize)
{
CopyStream(_oldStream, _newStream);
_newStream.Position = 0;
}
}
void InsertDetailIntoOldStream(Exception exception)
{
XmlDocument doc = new XmlDocument();
doc.Load(_newStream);
XmlNode detailNode = doc.SelectSingleNode("//detail");
try
{
detailNode.InnerXml = GetXmlExceptionInformation(exception);
}
catch(Exception exc)
{
detailNode.InnerXml = exc.Message;
}
XmlWriter writer = new XmlTextWriter(_oldStream, Encoding.UTF8);
doc.WriteTo(writer);
writer.Flush();
}
In the method ProcessMessage, you can see that the code waits till after the method has been serialized to XML (represented by SoapMessageStage.AfterSerialize) and is ready to be sent back to the client. That’s where the exception detail is injected into the stream, assuming an exception did occur.
InsertDetailIntoOldStream finds the detail node within the serialized stream and inserts exception information into that node. In order to make this information useful to both non .NET clients and .NET clients, the exception information is formatted as XML. However, in one of the nodes of that XML, I serialize the exception using a BinaryFormatter. That way, a .NET client can gain access to the full original exception.
string GetXmlExceptionInformation(Exception exception)
{
string format = "<Message>{0}</Message>"
+ "<Type>{1}</Type>"
+ "<StackTrace>{2}</StackTrace>"
+ "<Serialized>{3}</Serialized>";
return string.Format(format, exception.Message, exception.GetType().FullName, exception.StackTrace, SerializeException(exception));
}
string SerializeException(Exception exception)
{
MemoryStream stream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, exception);
stream.Position = 0;
return Convert.ToBase64String(stream.ToArray());
}
Security Note!, for a production system, you probably don’t want to serialize the original exception as it will contain a stack trace and could give out more information than you wish clients to the service to have. For debugging, however, this is quite useful.
Allow me to walk through how you can apply these classes in your own code. Below, I’ve written a method that simply throws an exception. You can see that I marked it with the SerializedExceptionExtension attribute.
[WebMethod, SerializedExceptionExtension]
public string ThrowNormalException()
{
throw new ArgumentNullException("MyParameter", "Exception thrown for testing purposes");
}
Now on the client, I simply make a call to the web service within a try/catch clause. In the snippet below, you’ll notice that I wrap the thrown exception with the SoapOriginalException class. That class is a helpful wrapper that knows how to deserialize an exception serialized using this technique. The original exception is accessed via the InnerException property.
void CallService()
{
TestService proxy = new TestService();
try
{
proxy.ThrowNormalException();
}
catch(SoapException e)
{
SoapOriginalException realException = new SoapOriginalException(e);
Console.WriteLine(realException.InnerException.Message);
}
}
If you’d like to try this technique out yourself and provide a critique, download the ExceptionInjectionWithSoapExtension.zip source files here. There are certainly some enhancements that could be made to the code to make it even more useful. Let me know if you make improvements.
[Listening to: When You Sleep - Cake - Prolonging the Magic (3:58)]
Wohoo! The little lady and myself will be in attendance as we watch Zinedine Zidane, Beckham, Ronaldo, Owen, Roberto Carlos and the rest of Real Madrid completely overpower and dismantle the lackluster Galaxy when they play an exhibition game at the Home Depot Center in Carson.
It’ll be interesting to see if Landon Donovan can scrape together a worthy performance in the face of such talent and show that he’s ready for the world stage.
I remember when living in Madrid, Spain just how revered Real Madrid is. They are a storied team with a rich history and a fantastic roster this year. Of course, too much star power can sometimes be a detriment, as we learned with the lakers last year, and as we saw this year as second place Real Madrid were upstaged by Barcelona for the Spanish League title.
Steven Clarke has an interesting post about the usability (or lack thereof) of the Factory Pattern.
In simple terms, the usability issue strikes when a developer knows she needs an instance of object Foo. So she tries to new one up like so...
Unfortunately Foo looks like this...
public class Foo
{
ÂÂÂÂprivate Foo() {}
}
Notice the private constructor? VS.NET’s intellisense dutifully tells her that she can’t create an instance of Foo in this way. So now how is she supposed to create her beloved Foo? The answer is that there’s probably a FooFactory laying around somewhere that’ll do just that for her. So now she has to go rooting around looking for that class, her rhythm and flow being disturbed in the process.
So is the answer to simply throw out the Factory pattern? Dear god no! This is one of those cases where perhaps the IDE could be a bit more helpful. Imagine if we could markup the class like so...
public class Foo
{
ÂÂÂÂ/// <summary>
ÂÂÂÂ/// Try using the FooFactory to create this class.
ÂÂÂÂ/// </summary>
ÂÂÂÂprivate Foo() {}
}
And that comment would show up when trying to directly create an instance of Foo. Wouldn’t that be wonderful? Or for you attribute lovers, maybe an attribute would be a better option.
[Factory(typeof(FooFactory))]
public class Foo
{
ÂÂÂÂprivate Foo() {}
}
Either way, the goal is to give the forlorn developer some help via Intellisense. All that API creators need to do is to add a bit of information to their classes and voila! Intellisense to the rescue. You’ve rescued the usability of the factory pattern.
[Listening to: Victorious - Tiësto - Parade of the Athletes (4:38)]
Dare may singlehandedly be responsible for delaying Longhorn, VS.NET 2005, Yukon and many other products as legions of programmers (Microsoft and otherwise) lose productivity by spending their time playing DHTML Lemmings, a faithful javascript reproduction of the classic game Lemmings.
Lemmings is probably one of the most popular games I’ve never played until now. It is quite addicting.
If you’re a fan of NPR and KCRW, make sure your voice is heard. The House will soon vote on budget cuts for public broadcasting and the issue is being painted as a liberal vs conservative battle.
I believe it is impossible for a person to be truly objective, but as far as news programs go, I think NPR does a great job of it. I think both sides of the political spectrum appreciate receiving news without the sensationalism and fear mongering so prevalent from its puerile cousin, television news. Here is the letter from KCRW in full...
Message from KCRW General Manager Ruth Seymour
Dear KCRW Listener,
I am writing you about an unfolding crises in Congress with regard to public broadcasting. Proposed funding cuts now before the full House pose a serious threat to public radio and television -- and to KCRW.
The proposed cut is 25% to KCRW's CPB grant this October and next October as well. Moreover adding the proposed additional cuts to PBS childrens' programs and station digital conversion -- the total reduction adds up to a whopping 45%!
Facility funding, which provided oportunities for stations to modernize and extend their service has already been zeroed out. These are the grants that helped KCRW purchase it's first modern transmitter in 1979 and launch NPR's Morning Edition. Later they enabled KCRW to extend sevice to Ventura and the
Antelope Valley.
If these cuts stand, KCRW may lose over $1,000,000 from its
operating revenue. This would severely impact KCRW's local programming and our ability to sustain NPR.
The Corporation for Public Broadcasting is the independent organization created by Congress to support public broadcasting and act as a heat shield against political interference. But now, ironically, the Corporation itself is providing the heat.
Chairman Ken Tomlinson has politicized matters by framing the issue of balance on news programs as liberal versus conservative. We vehemently object to this characterization which is intended to put public broadcasting on the defensive and influence program decisions.
- We cherish our editorial independence and the political diversity of the audience we have attracted.
- We believe in objective journalism, free from political constraints.
- While we welcome constructive criticism, we reject partisan judgements masquerading as impartial analysis.
We can't reverse the funding cuts by ourselves. We need your help.
THE MOST IMPORTANT VOICE IN PUBLIC BROADCASTING IS YOURS!
Please register your opinion by contacting your Congressional Representative right away.
The full House votes next Thursday or Friday.
Find your Congressional Representative at:
http://kcrw.convio.net/site/R?i=wkbWt29jsWNpftH33vy4eg.
Sincerely,
Ruth Seymour
KCRW General Manager
Visit KCRW.com for additional information and background:
You know what, I do want to express myself, okay. And I don't need 37 pieces of flair to do it.
No. I need a Flickr Badge! For those of you reading this from an aggregator, you’ll need to take a step out of the comfort of the aggregator into the scary world of “web browsing” and view my page from a browser to see the flickr badge on the right.
I know, I’ve gushed about Flickr in the past, but I like how easy they make it to integrate into your own website. They also allow you to put up a a nifty Flash version of a badge, but I settled for the simple HTML badge.
Now if you’re concerned about such things as XHTML validating markup, you really need to quit being so anal and get a life. Having said that, let me show you some small tweaks you’ll need to make so that your flickr badge validates as XHTML 1.0 Transitional (I haven’t tried strict yet). Us anal types can’ go around with invalid markup, now can we?
When you create your badge, Flickr will give you some code to inject into your web page. The first step is to take the style element and either move it inside the head element of your page or scrape its guts and slap them inside a css file.
After that, you’ll notice that there’s a script tag just before a tr tag. That tag essentially is a javascript repeater that repeats the following tr block. If you move it, you break the badge. Unfortunately, it doesn’t validate as is so I haacked it (get it? “haacked it” As in hack? Oh Never mind) by placing the script within a caption element.
Finally, I went through and replaced all the ampersands within the URLs with &. After that, voila! My homepage is back to being valid XHTML 1.0. Do I get a trophy or win prizes for this work? No. But I do get to sport this nifty piece of geek flair.
Just curious if any of my fantastic readers (or Google searchers, welcome. Nothing but love for ya) have experience with using Quickbooks Online. If so, let me know in the comments what your experience with it has been. Thank you.
Now repeat after me, “RSS is designed to be extended.”
Good. Now repeat it again. It’s old hat that Microsoft has engaged in some perhaps anti-competitive practices in the past, often referred to as their “embrace and extend” philosophy. But embracing and extending isn’t always a bad thing.
Of course, I should expect a knee-jerk reaction against the announcement from the Slashdot crowd, but it seems they’re not the only ones up in arms.
What’s interesting about these reactions is the amount of misinformation and ignorance being spewed forth.
Suddenly, “extend” has become a derogatory label. Yet these very same people will laud an application like Eclipse for its...gasp!...extensibility (and rightly so).
In this case, it’s hard to find a shred of so called “evil” in this announcement by Microsoft. They’ve chosen a CopyLeft license for Pete’s sake! You don’t get more open than that. You even have Lawrence Lessig applauding this, remember him? He“s the lawyer who helped the DOJ mount its Supreme Court showdown with Microsoft.
Face it folks, you’re just wrong this time. Microsoft releasing extensions to RSS is not going to be the death knell for RSS. An extension does not change or make proprietary the original RSS specification. As I said before, RSS is designed to be extended. Anyone can extend RSS. Heck, even I proposed an RSS extension, albeit one that gained just about zero traction (although I may sneak it into Subtext just to satisfy my megalomaniacal urges).
From the Lessig blog I learned that Microsoft is releasing its spec for “Simple Feed Extensions” under a Creative Commons Attribution-ShareAlike license, often referred to as a “CopyLeft” . People are free to modify and redistribute the spec so long as the modifications are licensed under a similar license.
This shows a couple things about Microsoft. First, that it is not (and probably never has been) a mono-culture. Secondly, that groups within Microsoft get it when it comes to RSS and know how to play nice. Bravo!
Anybody out there use a geolocation service they are happy with?
In case you’re unfamiliar with the term (and thus unlikely to be able to answer my question), Geolocation is the process of converting an IP Address into a geographic location. I think many services simply provide a database of ip address to geographic locations.
Also, how do these services handle AOL? Would every AOL user appear to be coming in from Virginia? Thanks if you have any insight!
I’ve been intentionally quiet about how Subtext is progressing (apart from a couple minor posts on how to obtain the code via CVS). My reticense is certainly not from lack of excitement or enjoyment of the project. Working on Subtext has been about the most enjoyable software development project I’ve ever had the pleasure to work on. So much so, that I’ve fallen a bit behind on my “real” work. Unfortunately this has caught up to me as I now have two projects with a potential third not far behind to work on (Yes, I know. A good problem to have, so quitcher belly-aching). This is very exciting for me as it may herald the beginning of a company. But it also means I need to slow down on Subtext a bit.
The reason I have been so reticent about Subtext up to this point is that we have not yet had a release. It was suggested to me that I probably should’t have waited to make the original Subtext announcement until I had a first release. This is definitely good advice for one who is starting an open source project. However, it may have helped in my case that I was building on an existing project familiar to many. And the few who did jump at the chance to help have been invaluable in what progress we’ve made so far.
What progress you ask? Well as you can see in this post, we are making great progress in having a nice logo. This is not the final logo, but probably really close. As you know, if a project has a nice logo, the code must really be nice. ;)
Subtext is progressing nicely in other areas too. So much so that I upgraded my blog to Subtext after a particularly withering comment spam attack. Subtext hasn’t yet completely eradicated comment spam, but it definitely has made a difference already.
In any case, I hoped not to talk much about it until we did have a release, but here I am anyways blabbing my mouth fingers. The goal of the first release is to generate excitement about the project and have many more contributors help with the next release. By talking about it now rather than waiting, I hope to try and encourage people to contribute before the first release. As my involvement declines for a few months (hopefully at most), I hope to have others pick up some of the slack and carry the torch sub forward.
Project Website
If you’re interested in tracking the progress of subtext, check out our new project website at http://subtextproject.com/. It is definitely a work in progress, but it has plenty of instructions for how to get the latest source code and how to contribute. Not only that, the site itself is in our CVS repository. So if you want to contribute to our documentation efforts (please! please!), you can submit patches to the project site.
Roadmap
Also be sure to check out the updated Roadmap.
Well that’s it for me. I spent today on some Subtext housekeeping to clear the way for others to make some nice progress. I’ll probably be much more quite for a few months, though I will respond to emails and such and continue to try and guide the process. It’s been and continues to be fun sailing.
In a recent post I outlined step by step how to obtain the source code for Subtext as a non-developer. Well I was a bit sloppy and made a couple of mistakes in the post (now corrected).
However, I feel a bit bad about it. It’s not like me to be so sloppy and give incorrect information. I decided I must pay penance! These instructions apply to those who want to look at the source code on a development machine.
The Easier Way!
I created a simple batch file you can use to execute the CVS command for you. So my updated steps are:
- As before, make sure you have TortoiseCVS installed.
- Create a database in SQL Server named “SubtextData” and make sure your database server has an ASPNET login.
- Create an ASPNET user using the ASPNET login for the SubtextData database.
- Download and unzip the batch file to your projects folder (for me, I would place this file in my “c:\Projects” folder.
- Now double click the batch file.
If you install TortoiseCVS in a location other than your program files, you will need to modify the batch file to point to the correct location.
When you run the batch file, it downloads all the source code from CVS and then runs a downloaded script named “CreateSubtextVdir.vbs” that will set up a virtual directory in IIS pointing to the correct location. All you have to do is compile and browse to http://localhost/Subtext.Web/.
Again, I hope this makes it easier to grab the latest bits and play around with it.
[Listening to: rez/Cowgirl - Underworld - Everything Everything: Live [IMPORT] [LIVE] (11:47)]
I can have a very filthy mouth when pissed off. Take today for example, my dog was witness to a blistering stream of profanities as I found that my site was down. I was hit with a torrent of comment spam like nothing I’ve seen before.
Since I have my blog configured to send me an email when someone comments, the mail server was trying to send out 500 messages in five minutes. At least according to my hosting provider who turned off my site in response to the massive flood of email. All in all, the spammers posted over a thousand messages in a very short while.
This of course prompted me to perform an emergency upgrade of my blog to the latest unreleased version of Subtext. I wasn’t quite ready to perform this upgrade as I was hoping to get a few more comment spam fighting features implemented, but I was getting tired of the bombardment.
In the process I fixed a few bugs here and there, mostly related to the difference between developing on your own server but being hosted on a shared server.
At least now, I can throttle comments so that too many don’t come in all at once. This particular storm of comments appears to have originated in China (at least the comments and urls were in chinese). I think I may have to post a few posts about freedom, democracy, and the American way in order to get my blog banned in China. ;)
[Listening to: Life in Mind - Paul Oakenfold - Global Underground 007 New York CD1 (4:48)]
Who’s ever gotten Jet Lag flying from Oakland to Los Angeles? ;)
UPDATE: Sorry, but my previous instructions contained some errors. I’ll make it up to you. In the meanwhile, here are the corrections.
If you don’t have developer access to the Subtext project on SourceForge but want to take a look at the latest version of source code and compile it yourself, just follow the following steps. I simply borrowed this list from Scott’s post and modified it for Subtext.
- Download TortoiseCVS and install it.
- Right click on the folder where you generally create projects (for me it would be in the c:\Projects folder) and select “CVS Checkout”
- In the CVSROOT text box, enter in this: :pserver:anonymous@cvs.sourceforge.net:/cvsroot/subtext and in the Module text box enter “SubtextSystem”
- Hit OK. You'll get all of Subtext. You should now have a SubtextSystem folder within your projects folder.
- There is a file named “CreateSubtextVdir.vbs” that will setup Subtext in IIS as a Virtual Directory (thanks again Scott!)
- Now you’re ready to compile and play around.
NOTE: When you do this you are implicitly getting a label in source control called “HEAD.” That’s the latest stuff that the Subtext team has checked into CVS.
Until Subtext has a release, that’s all there is to play with. Once we do have releases, I’ll provide info on how to download a specific release.
Scott Hanselman provides an excellent writeup of how to use GNU Patch.exe with CVS and DIFF files. This is very helpful as it is the one (of perhaps many) thing missing from my Quickstart Guide to CVS and SourceForge for Windows developers.
When I get a free moment, I will update my Quickstart.
I’m in San Francisco for a working meeting for a client. We’re doing a bit of project planning and working through the specs and schematics. The thing I love about San Francisco is I never have a bad time, even if I’m only here for two days and one night.
Last night, my buddy Micah took me, his sister, and her boyfriend out to a nice bar/club named “Milk”. The DJs mixed it up with a bit of neo-soul, hip-hop, etc.. and we closed the place down. Afterwards, I had real trouble getting to sleep, finally snoozing at around five AM.
I’m so tired at this point, my head can’t even make sense of it. I feel like I’m walking in an alternate world than everyone else. Like I’m the one black and white character in a color TV show. The slight bit of tunnel vision doesn’t help either. And no, I did not take any “foreign” substances last night, unless you count just a tiny eensy weensy bit of alcohol.
This is not your ordinary history of computer science quiz. From the site...
Can you tell a coder from a cannibal? Try to work out which of the following spent their
time hacking computers and which preferred hacking away at corpses instead.
Take the quiz.
We got hitched! :)
Happy Anniversary Akumi!

For those of you not from the U.S. or England, Durex is a English brand of condoms sold in the U.K. and the U.S.
Just so we’re all clear about this, the convenience of the CommentAPI, that nifty little service that allows users to make comments to your blog from the comfort of their favorite RSS aggregator, comes at a cost. Enabling the CommentAPI supplies a back door for comment spammers who want to bypass the CAPTCHA guard posted at the front door.
I was just chatting with Andrew about this and we realized it would be quite easy to add CAPTCHA support to the CommentAPI if we could get both RSS Aggregator developers and blog engine developers to agree on how to update to the CommentAPI to support a CAPTCHA image url or a CAPTCHA text question. The RSS Aggregator would then display this image or text, and provide the user a field in the comment dialog to supply the answer to the CAPTCHA challenge, which the CommentAPI would validate with the CAPTCHA control. Of course this wouldn’t close the CAPTCHA backdoor for Trackbacks and Pingbacks.
In the meantime, I tend to favor non-CAPTCHA approaches to comment spam filtering for this very reason. I want to fight comment spam tooth and nail with every resource I have before I turn off the CommentAPI on my blog. Likewise, I still support Trackbacks because I personally have found them more beneficial than detrimental so far.
In any case, Subtext will provide configuration options to turn each of these services on or off individually so that users have full control of comment entry points.
UPDATE: I have recently posted a newer and better version of this code on my blog.
As I’ve stated before, I’m a big fan of completely self-contained unit tests. When unit testing ASP.NET pages, base classes, controls and such, I use the technique outlined by Scott Hanselman in this post. In fact, several of the unit tests for RSS Bandit use this technique in order to test RSS auto-discovery and similar features.
However, there are cases when I want a “lightweight” quick and dirty way to test library code that will be used by an ASP.NET project. For example, take a look at this very contrived example that follows a common pattern...
/// <summary>
/// Obtains some very important information.
/// </summary>
/// <returns></returns>
public SomeInfo GetSomeInfo()
{
SomeInfo info = HttpContext.Current.Items["CacheKey"] as SomeInfo;
if(info == null)
{
info = new SomeInfo();
HttpContext.Current.Items["CacheKey"] = info;
}
return info;
}
The main purpose of this method is to get some information in the form of the SomeInfo class. Normally, this would be very straightforward to unit test except for one little problem. This method has a side-effect. Apparently, it’ll cost you to obtain this information, so the method checks the Context’s Items dictionary (which serves as the current request’s cache) first before paying the cost to create the SomeInfo instance. Afterwards it places that instance in the Items dictionary.
If I try and test this method in NUnit, I’ll run into a NullReferenceException when attempting to access the static Current property of HttpContext.
One option around this is to factor the logic between the caching into its own method and test that. But in this case, I want to test that the caching works and doesn’t cause any unintended consequences.
Another option is to fire up Cassini in my unit test, create a website that uses this code, and test the method that way, but that’s a “heavy” (and potentially very indirect) way to test this method.
As I stated before, I wanted a “lightweight” means to test this method. There wouldn’t be a problem if HttpContext.Current was a valid instance of HttpContext. Luckily, the static Current property of HttpContext is both readable and writeable. All it takes is to set that property to a properly created instance of HttpContext. However, creating that instance wasn’t as straightforward as my first attempt. I’ll spare you the boring details and just show you what I ended up with.
I wrote the following static method in my UnitTestHelper class. All the write statements to the console shows the values for commonly accessed properties of the HttpContext Note that this method could be made more general for your use. This is the version within Subtext.
/// <summary>
/// Sets the HTTP context with a valid simulated request
/// </summary>
/// <param name="host">Host.</param>
/// <param name="application">Application.</param>
public static void SetHttpContextWithSimulatedRequest(string host, string application)
{
string appVirtualDir = "/";
string appPhysicalDir = @"c:\projects\SubtextSystem\Subtext.Web\";
string page = application.Replace("/", string.Empty) + "/default.aspx";
string query = string.Empty;
TextWriter output = null;
SimulatedHttpRequest workerRequest = new SimulatedHttpRequest(appVirtualDir, appPhysicalDir, page, query, output, host);
HttpContext.Current = new HttpContext(workerRequest);
Console.WriteLine("Request.FilePath: " + HttpContext.Current.Request.FilePath);
Console.WriteLine("Request.Path: " + HttpContext.Current.Request.Path);
Console.WriteLine("Request.RawUrl: " + HttpContext.Current.Request.RawUrl);
Console.WriteLine("Request.Url: " + HttpContext.Current.Request.Url);
Console.WriteLine("Request.ApplicationPath: " + HttpContext.Current.Request.ApplicationPath);
Console.WriteLine("Request.PhysicalPath: " + HttpContext.Current.Request.PhysicalPath);
}
You’ll notice this code makes use of a class named SimulatedHttpRequest. This is a class that inherits from SimpleWorkRequest which itself inherits from HttpWorkerRequest. Using Reflector, I spent a bit of time looking at how the HttpContext class implements certain properties. This allows me to tweak the SimulatedHttpRequest to mock up the type of request I want. The code for this class is...
/// <summary>
/// Used to simulate an HttpRequest.
/// </summary>
public class SimulatedHttpRequest : SimpleWorkerRequest
{
string _host;
/// <summary>
/// Creates a new <see cref="SimulatedHttpRequest"/> instance.
/// </summary>
/// <param name="appVirtualDir">App virtual dir.</param>
/// <param name="appPhysicalDir">App physical dir.</param>
/// <param name="page">Page.</param>
/// <param name="query">Query.</param>
/// <param name="output">Output.</param>
/// <param name="host">Host.</param>
public SimulatedHttpRequest(string appVirtualDir, string appPhysicalDir, string page, string query, TextWriter output, string host) : base(appVirtualDir, appPhysicalDir, page, query, output)
{
if(host == null || host.Length == 0)
throw new ArgumentNullException("host", "Host cannot be null nor empty.");
_host = host;
}
/// <summary>
/// Gets the name of the server.
/// </summary>
/// <returns></returns>
public override string GetServerName()
{
return _host;
}
/// <summary>
/// Maps the path to a filesystem path.
/// </summary>
/// <param name="virtualPath">Virtual path.</param>
/// <returns></returns>
public override string MapPath(string virtualPath)
{
return Path.Combine(this.GetAppPath(), virtualPath);
}
}
Within the SetUp method of my TestFixture, I call this method like so...
[SetUp]
public void SetUp()
{
_hostName = UnitTestHelper.GenerateUniqueHost();
UnitTestHelper.SetHttpContextWithBlogRequest(_hostName, "MyBlog");
}
Unfortunately, this so called “lightweight” approach has its limits. Any call in your code to HttpContext.Currert.Request.MapPath will throw an exception. I tried working around this, but it looks like I’m at an impasse. The MapPath method makes use of the HttpRuntime.AppDomainAppPath property. Unfortunately, I cannot simulate the HttpRuntime in a lightweight manner. There is a way to run the code being tested within an HttpRuntime, but that, of course, is the heavyweight Cassini method mentioned above.
[Listening to: The Joint/Wavefrint - DJ Hyper - Bedrock Breaks CD1 (5:35)]
So it's maybe thirteen years too late, but I finally have my first pair of Air Jordans. Yeah, they don't have anywhere near the cachet they did back in the day, but hey, better late than never. Here's a photo to commemorate the occasion.

Michael thanks you... all the way to the bank.
I remember when I was a high-school ball player (made JV. At 5' 9", I was a bit short for Varsity), I positively drooled at the idea of owning a pair of Air Jordans when they came out. They defined hotness for the realm of basketball shoes, though they seemed to do little to actually improve my teammates' skills. I remember one point guard in particular who claimed the coveted title of being the "First" to own a pair (Remember how important it was to be the "First"? New toilet model coming out. I had it first!). He would show up to practice in head to toe Jordan gear complete with the tongue sticking out and proceed to build a very sturdy tenenment with the bricks he tossed up.
For a military brat, these emblems of Basketball glory were outside the realm of affordability. But now as a hot-shot independent consultant, they are still outside the realm of affordability. The difference now is that I have less sense, so I bought a pair anyways. They certainly are a lot cheaper than they were back in the day.
To justify this purchase, I give you a picture of my last pair. As you can see, I do wait till the last minute and beyond, before buying a new pair of shoes. Now excuse me while I purchase a new pair of Copa Mundials to replace my thoroughly trashed soccer cleats.

Look what the cat dragged in.
Oh man, I have been head deep into “real” work lately, which explains the relative silence on my blog. In any case, it’s time to jump back in the fray with some light technical content.
Starting with version 2.2.1, the ever so handy NUnit unit-testing framework finally supports building custom test attributes. This allows you to create your own attributes that you can attach to tests to allow you to run custom code before and after a test and handle what to do if an exception is thrown or not thrown.
Roy Osherove, a unit-testing maestro, wrote up a simple abstract base class developers can implement that greatly simplifies the process of creating a custom test attribute.
In an MSDN article, Roy outlines various methods for dealing with database access within unit tests including a particularly promising method using COM+ 1.5. He mentions that he’s implemented a Rollback attribute for a custom version of NUnit he calls NUnitX.
Not wanting to run a custom implementation of NUnitX, I quickly implemented a Rollback attribute for NUnit 2.2.1. Heck, it was quite easy considering that Roy did all the fieldwork.
Unfortunately, I ran into a few problems. The custom attribute framework is not quite fully baked yet. When you apply a custom test attribute, your attribute may break other attributes. Case in point, my ExpectedException attributes suddenly stopped working. Looking through the NUnit codebase, it appears that the first attribute loaded handles the ProcessNoException and ProcessException method calls.
This is a known issue and an NUnit developer stated that he’s working on it. In the meanwhile, I worked around this issue with a beautiful kludge. I simply extended my Rollback attribute to absorb the functionality of an ExpectedException attribute. This is really ugly, but it does the job. So if you use this Rollback attribute, you can also specify an expected exception like so:
[Rollback(typeof(InvalidOperationException))]
I know, “ewwww!”. This is essentially an attribute doing double work. It’s probably better to name it "RollbackExpectedException" attribute. But I hope to remove this functionality at a later date when the custom attribute support in NUnit is more full baked.
The second problem I ran into is that this approach enlists the native Distributed Transaction Manager for SQL Server (in my situation). In one project, I’m testing against a remote database and native transactions are turned off for security purposes. The solution in this case is to use TIP, or Transaction Internet Protocol. This would require modifying the "BeforeTestRun" method to (notice the added line in bold):
ServiceConfig config = new ServiceConfig();
config.TipUrl = "http://YourTIPUrl/";
config.Transaction = TransactionOption.RequiresNew;
ServiceDomain.Enter(config);
So far, I haven’t been able to get our system administrator to enable TIP so I haven’t fully tested this last bit of chicanery.
In any case, make sure to read Roy’s articles noted above before downloading this code. I’ve made some slight modifications to his base class to reflect personal preferences. Let me know if you find this useful.
[Listening to: Wake Up - Rage Against The Machine - Rage Against The Machine (6:04)]
This is what I was working on before the siren call of independent consulting lured me away.
The new product, which Philp projects to go live next month, will be known as SkillJam Mobile. For the initial product launch, SkillJam Mobile will be separate from the SkillJam.com site, giving users separate log-ons. Philp said the company hopes to combine the two sites in the future.
SkillJam Mobile will offer what Philp calls multipack gaming, an innovative concept in the mobile space. Most carriers have games on their systems but are able to deliver them only one at a time.
At the time that I left, much of the infrastructure work had been completed, though I made myself available to do some contract work to help finish up some of the loose ends, which they took advantage of. It’ll be interesting to see how well this does.
This is my feeble attempt win an all expense trip to the PDC this year. All I have to do is explain why I want to attend. Unfortunately, I’ll be judged on creativity, value to the community, writing quality and style. It was my hope that my dashing good looks and slipping someone a freshly minted bill would suffice.
Well the reason I want to attend is simple, it’s to play XBox 360... AND to get a heads up on the upcoming technology Microsoft is churning out. I’m particularly interested in future versions of VS.NET and ASP.NET. I hope to get some ideas to apply to Subtext.
As for sharing with the community, there’s this blog thing I have. I’ve recently inherited a video camera so I will very likely place videos and photographs on here, along with witty and insightful commentary (assuming I can hire that witty and insightful off-shore ghost writer). Like a relentless avalanche, I’ll go door to door and tell people in person if that’ll help.
Lastly, I’d like to drop the economic argument: I live in Los Angeles, so Microsoft can stay lean and mean and save a buck on the air fare voucher, though I’d gladly accept the hotel accomodations. Bill and Steve will pat you on your back for your resourcefulness.
Via Rory’s post here, I’ve discovered the Obsolete Technology Website.
The fact that this site evokes nostalgia only reinforces two facts about me, that I am a total geek and I’m getting old. I love the write-up of my very first computer (which I still own and have laying around here somewhere).
The gray/silver color scheme was fetching for the original TRS-80 Model I computer, but it just doesn't work on the Color Computer - it has to be one of the ugliest computers ever.
Ahhh yeah!
Later, when several of my friends were riding the Commodore 64 wave, I jumped one step ahead with my second computer, the Commodore 128 (one-piece model). In sense, this wasn’t a step ahead at all as the Commodore 128 was just a glorified Commodore 64 with a nicer looking case. Just about nobody jumped at the chance to write software that took advantage of the C128 Mode or the CP/M mode. I pretty much spent most of the time using it in C64 mode.
My third, and last computer before switching over to the Wintel universe, was every geek boy’s wet dream at the time, the Amiga 500. Unfortunately the site doesn’t have a write-up of the Amiga 500 specifically, but you can read up on the Amiga 2000 which came out the same year.
Ahhh memories...
Ah man, this isn’t available in my neigborhood yet, but they’re offering 15 Mbps/2 Mbps internet access for $49.95. That’s what I’m paying now for my cable service.
I can’t wait till they roll this out in our neighborhood.
Looking at my SPAM filter, I notice that nearly a quarter of my emails appear to be from PayPal. Of course, these are all spoofed to appear that way.
If you get an email from PayPal, DO NOT CLICK ON ANY LINKS IN THE EMAIL!
Instead, fire up your browser of choice, and type in www.paypal.com in the address bar. Nearly all of these emails are fakes. Here’s an example of a particularly tricky one that raised alarms and almost caused a knee jerk reaction till I realized it was a fake. It played upon a simple fear.
You have added
brian12313@yahoo.com
as a new email address for your PayPal account.
If you did not authorize this change or if you need assistance with your account, please contact PayPal customer service at:
https://www.paypal.com/row/wf/f=ap_email
Thank you for using PayPal!
The PayPal Team
Please do not reply to this e-mail. Mail sent to this address cannot be answered. For assistance, log in to your PayPal account and choose the "Help" link in the header of any page.
----------------------------------------------------------------
PROTECT YOUR PASSWORD
NEVER give your password to anyone and ONLY log in at
https://www.paypal.com/.
Protect yourself against fraudulent websites by opening a new web browser (e.g. Internet Explorer or Netscape) and typing in the PayPal URL every time you log in to your account.
---------------------------------------------------------------
PayPal Email ID PP007
This is a standard notice when adding a new email address to your PayPal account. What caught my attention is that the email address has the name brian. My brother is named Brian, so instinctually I wondered if he made a mistake with his own paypal account, adding me as an address.
But soon, I realized that this has to be a scam, simply because EVERY email I seemingly get from PayPal appears to be a scam.
Notice the URL https://www.paypal.com/row/wf/f=ap_email so helpfully included to ostensibly help you contact PayPal customer service. In my email, this was a link. When I hovered my mouse over it, it’s displays a completely different URL at some server with the IP 220.80.212.211. A quick DNS Lookup shows this is not a PayPal server.
In fact, EVERY "link" in this URL points to that IP address, even the word brian12313@yahoo.com which you would expect to be a mailto: link. Very sneaky.
I’ve heard of writer’s block, but never dealt with coder’s block until today. Seriously, I’ve always been able to just unleash that kernel of code simmering inside in a big pop of keyboard slamming.
As an aside, my wife and her friend happened to walk in on a coding session one day and they remarked that they could easily do what I do. Why, I’m simply stabbing at the keys at random! They proceeded to mimic me jamming the keyboard as an insane pianist attempting to perform a Liszt piece at twice the speed might do. Hmm, hopefully my clients don’t find out and replace me with a monkey.
But today, alas, I’m tipping my head to the side, and nothing is pouring out. Zip. Guess it’s time to take a break and maybe buy some books.
I just finished reading part 2 of the Bill Venners interview with Erich Gamma and Erich so eloquently distills some of what I was trying to say in a recent post.
It’s interesting to note how thinking about building systems has changed in the ten years since Design Patterns was published. Bill Venners quotes the GOF book as saying
The key to maximizing reuse lies in anticipating new requirements and changes to existing requirements, and in designing your systems so they can evolve accordingly. To design a system so that it?s robust to such changes, you must consider how the system might need to change over its lifetime. A design that doesn?t take change into account risks major design in the future.
This is certainly something I was taught when I first started off as a developer, but I think now, it?s becoming more and more clear that speculation carries a lot of risk and can be more harmful than helpful. I learned that the hard way, as clients are a fickle lot, and you can guess what they?ll ask for next as easily as you can guess the next super lotto numbers.
Erich?s approach to building an extensibility model with Eclipse reflects how I try to approach projects I work on. In essence, experience a little pain (be it duplication, etc...) before refactoring with a pattern.
I eagerly anticipate part 3 of the interview. Be sure to also read Part 1 of the interview.
I’ve been following with interest Shelley’s progress with WordForm, a blogging engine. I hadn’t realized that WordForm was a fork in WordPress until she recently mentioned it.
In this particular post she describes some of the work she’s doing to handle metadata for images. She’s extracting EXIF data from images and storing as RDF statements in the database. She’s also pulling EXIF data from Flickr via its RESTful API. This is some sweet stuff that I hope finds its way into Subtext sometime in the future, though we have more pressing immediate concerns.
I’ll just wait to see how it pans out for WordForm and we’ll STEAL STEAL STEAL (of course giving full credit and props back to Shelley). ;)
So they say that email is an addiction.
Isn’t that like saying that breathing is an addiction?
I know it’s been around a good while now and has been the darling of the blogging community far that time, but I only recently started to play with Flickr. My initial resistance was due to my complete dissatisfaction with other online photo management tools such as oFoto, Yahoo Photos, SnapFish etc...
However, after spending only a few moments with Flickr, I can see that Flickr has put a lot of thought into photo management in an effort to get it right. It’s so good that I am reconsidering whether I even need a desktop photo management software. I probably won’t give up Photoshop Album just yet since I don’t want EVERY photo online. Besides, you never know when a company will go out of business, taking my photos with it. However my top feature request for the next version is Flickr integration.
I’ve been emailing some friends trying to get them to join. My photos are located at http://flickr.com/photos/haacked/. Feel free to add your own tags if you have relevant information.
There are two things I love about Flickr so far, its social tagging format (I can allow anyone to add tags to my photos, rather than trying to organize everything myself and I can add tags to my friends' photos) and its API. I haven’t played with the API directly, but the fact that there are some really cool tools for uploading photos quickly and easily is evidence that they’ve really thought through how to let others extend Flickr.
So give it a shot, and try not to waste too much playing with it when you should be working.