June 2010 Blog Posts
My son and I returned from a week long vacation to visit my parents in Anchorage Alaska last night. Apparently, having the boys out of the house was quite the vacation for my wife as well. :)
We had a great time watching the World Cup and going on outings to the zoo as well as hiking.
Well, at least one of us was hiking while another was just enjoying the ride. We hiked up a trail to Flattop which has spectacular views of Anchorage. Unfortunately, we didn’t make it all the way to the top as the trail became a bit too much while carrying a toddler who was more interested in watching Go, Diego, Go episodes on his iPod.
Funny how all that “hiking” works up an appetite.
Also, while in Alaska I gave a talk on ASP.NET MVC 2 to the local .NET User Group. It was their second meeting ever and somehow, in the delirium of perpetual sunlight, I spent two hours talking! It was slated to be a one hour talk.
I didn’t see a hint of resentfulness in the group though as they peppered me with great questions after the talk. Apparently, some of them are fans of .NET. ;)
The other thing I was able to do while in Alaska was finish up a bug fix release of Subtext in the wake of our big 2.5 release. There were some high priority bugs in that release. Simone has the details and breakdown on the Subtext 2.5.1 release.
In my last blog post, I wrote about the proper way to check for empty enumerations and proposed an IsNullOrEmpty method for collections which sparked a lot of discussion.
This post covers a similar issue, but from a different angle. A very long time ago, I wrote about my love for the null coalescing operator. However, over time, I’ve found it to be not quite as useful as it could be when dealing with strings. For example, here’s the code I might want to write:
public static void DoSomething(string argument) {
var theArgument = argument ?? "defaultValue";
Console.WriteLine(theArgument);
}
But here’s the code I actually end up writing:
public static void DoSomething(string argument) {
var theArgument = argument;
if(String.IsNullOrWhiteSpace(theArgument)) {
theArgument = "defaultValue";
}
Console.WriteLine(theArgument);
}
The issue here is that I want to treat an argument that consists only of whitespace as if the argument is null and replace the value with my default value. This is something the null coalescing operator won’t help me with.
This lead me to jokingly propose a null or empty coalescing operator on Twitter with the syntax ???. This would allow me to write something like:
var s = argument ??? "default";
Of course, that doesn’t go far enough because wouldn’t I also need a null or whitespace coalescing operator???? ;)
Perhaps a better approach than the PERLification of C# is to write an extension method that normalizes string in such a way you can use the tried and true (and existing!) null coalescing operator.
Thus I present to you the AsNullIfEmpty and AsNullIfWhiteSpace methods!
Here’s my previous example refactored to use these methods.
public static void DoSomething(string argument) {
var theArgument = argument.AsNullIfWhiteSpace() ?? "defaultValue";
Console.WriteLine(theArgument);
}
You can also take the same approach with collections.
public static void DoSomething(IEnumerable<string> argument) {
var theArgument = argument.AsNullIfEmpty() ?? new string[]{"default"};
Console.WriteLine(theArgument.Count());
}
The following is the code for these simple methods.
public static class EnumerationExtensions {
public static string AsNullIfEmpty(this string items) {
if (String.IsNullOrEmpty(items)) {
return null;
}
return items;
}
public static string AsNullIfWhiteSpace(this string items) {
if (String.IsNullOrWhiteSpace(items)) {
return null;
}
return items;
}
public static IEnumerable<T> AsNullIfEmpty<T>(this IEnumerable<T> items) {
if (items == null || !items.Any()) {
return null;
}
return items;
}
}
Another approach that some commenters to my last post recommended is to write a Coalesce method. That’s also a pretty straightforward approach which I leave as an exercise to the reader. :)
While spelunking in some code recently I saw a method that looked something like this:
public void Foo<T>(IEnumerable<T> items) {
if(items == null || items.Count() == 0) {
// Warn about emptiness
}
}
This method accepts a generic enumeration and then proceeds to check if the enumeration is null or empty. Do you see the potential problem with this code? I’ll give you a hint, it’s this line:
items.Count() == 0
What’s the problem? Well that line right there has the potential to be vastly inefficient.
If the caller of the Foo method passes in an enumeration that doesn’t implement ICollection<T> (for example, an IQueryable as a result from an Entity Framework or Linq to SQL query) then the Count method has to iterate over the entire enumeration just to evaluate this expression.
In cases where the enumeration that’s passed in to this method does implement ICollection<T>, this code is fine. The Count method has an optimization in this case where it will simply check the Count property of the collection.
If we translated this code to English, it’s asking the question “Is the count of this enumeration equal to zero?”. But that’s not really the question we’re interested in. What we really want to know is the answer to the question “Are there any elements in this enumeration?”
When you think of it that way, the solution here becomes obvious. Use the Any extension method from the System.Linq namespace!
public void Foo<T>(IEnumerable<T> items) {
if(items == null || !items.Any()) {
// Warn about emptiness
}
}
The beauty of this method is that it only needs to call MoveNext on the IEnumerable interface once! You could have an infinitely large enumeration, but Any will return a result immediately.
Even better, since this pattern comes up all the time, consider writing your own simple extension method.
public static bool IsNullOrEmpty<T>(this IEnumerable<T> items) {
return items == null || !items.Any();
}
Now, with this extension method, our original method becomes even simpler.
public void Foo<T>(IEnumerable<T> items) {
if(items.IsNullOrEmpty()) {
// Warn about emptiness
}
}
With this extension method in your toolbelt, you’ll never inefficiently check an enumeration for emptiness again.
Deploying a Subtext skin used to be one of the biggest annoyances with Subtext prior to version 2.5. The main problem was that you couldn’t simply copy a skin folder into the Skins directory and just have it work because the configuration for a given skin is centrally located in the Skins.config file.
In other words, a skin wasn’t self contained in a single folder. With Subtext 2.5, this has changed. Skins are fully self contained and there is no longer a need for a central configuration file for skins.
What this means for you is that it is now way easier to share skins. When you get a skin folder, you just drop it into the /skins directory and you’re done!
In most cases, there’s no need for any configuration file whatsoever. If your skin contains a CSS stylesheet named style.css, that stylesheet is automatically picked up. Also, with Subtext 2.5, you can provide a thumbnail for your skin by adding a file named SkinIcon.png into your skin folder. That’ll show up in the improved Skin picker.
When To Use A Skin.config File
Each skin can have its own manifest file named Skin.config. This file is useful when you have multiple CSS and JavaScript files you’d like to include other than style.css (though even in this case it’s not absolutely necessary as you can reference the stylesheets in PageTemplate.ascx directly).
The other benefit of using the skin.config file to reference your stylesheets and script files is you can take advantage of our ability to merge these files together at runtime using the StyleMergeMode and ScriptMergeMode attributes.
Also, in some cases, a skin can have multiple themes differentiated by stylesheet as described in this blog post. A skin.config file can be used to specify these skin themes and their associated CSS file.
Creating a Skin.config file
Creating a skin.config file shouldn’t be too difficult. If you already have a Skins.User.config file, it’s a matter of copying the section of that file that pertains to your skin into a skin.config file within your skin folder and removing some extraneous nodes.
Here’s an example of a new skin.config file for my personal skin.
<?xml version="1.0" encoding="utf-8" ?>
<SkinTemplates>
<SkinTemplate Name="Haacked-3.0">
<Scripts>
<Script Src="~/scripts/lightbox.js" />
<Script Src="~/scripts/XFNHighlighter.js" />
</Scripts>
<Styles>
<Style href="~/css/lightbox.css" />
<Style href="~/skins/_System/csharp.css" />
<Style href="~/skins/_System/commonstyle.css" />
<Style href="~/skins/_System/commonlayout.css" />
<Style href="~/scripts/XFNHighlighter.css" />
<Style href="IEPatches.css" conditional="if IE" />
</Styles>
</SkinTemplate>
</SkinTemplates>
If you compare it to the old format, you’ll notice the <Skins> element is gone and there’s no need to specify the TemplateFolder since it’s assumed the folder containing this file is the template folder.
Hopefully soon, we’ll provide more comprehensive documentation on our wiki so you don’t have to go hunting around my blog for information on how to skin your blog. My advice is to copy an existing skin and just tweak it.
Wow, has it already been over a year since the last major version of Subtext? Apparently so.
Today I’m excited to announce the release of Subtext 2.5. Most of the focus on this release has been under the hood, but there are some great new features you’ll enjoy outside of the hood.
Major new features
- New Admin Dashboard: When you login to the admin section of your blog after upgrading, you’ll notice a fancy schmancy new dashboard that summarizes the information you care about in a single page.
The other thing you’ll notice in the screenshot is the admin section received a face lift with a new more polished look and feel and many usability improvements. - Improved Search: We’ve implemented a set of great search improvements. The biggest change is the work that Simone Chiaretta did integrating Lucene.NET, a .NET search engine, as our built-in search engine. Be sure to check out his tutorial on Lucene.NET. Also, when clicking through to Subtext from a search engine result, we’ll show related blog posts. Subtext also implements the OpenSearch API.
Core Changes
We’ve put in huge amounts of effort into code refactoring, bulking up our unit test coverage, bug fixes, and performance improvements. Here’s a sampling of some of the larger changes.
- Routing: We’ve replaced the custom regex based URL handling with ASP.NET Routing using custom routes based on the page routing work in ASP.NET 4. This took a lot of work, but will lead to better control over URLs in the long run.
- Dependency Injection: Subtext now uses Ninject, an open source Dependency Injection container, for its Inversion of Control (IoC) needs. This improves the extensibility of Subtext.
- Code Reorganization and Reduced Assemblies: A lot of work went into better organizing the code into a more sane and understandable structure. We also reduced the overall number of assemblies in an attempt to improve application startup times.
- Performance Optimizations: We made a boat load of code focused performance improvements as well as caching improvements to reduce the number of SQL queries per request.
- Skinning Improvements: This topic deserves its own blog post, but to summarize, skins are now fully self contained within a folder. Prior to this version, adding a new skin required adding a skin folder to the /Skins directory and then modifying a central configuration file. We’ve removed that second step by having each skin contain its own manifest, if needed. Most skins don’t need the manifest if they follow a set of skin conventions. For a list of Breaking changes, check out our wiki.
Upgrading
Because of all the changes and restructuring of files and directories, upgrading is not as straightforward as it has been in the past.
To help with all the necessary changes, we’ve written a tool that will attempt to upgrade your existing Subtext blog.
I’ve recorded a screencast that walks through how to upgrade a blog to Subtext 2.5 using this new tool.
Installation
Installation should be as easy and straightforward as always, especially if you install it using the Web Platform Installer (Note, it may take up to a week for the new version to show up in Web PI). If you’re deploying to a host that supports SQLExpress, we’ve included a freshly installed database in the App_Data folder.
To install, download the zip file here and follow the usual Subtext installation instructions.
More information
We’ll be updating our project website with more information about this release in the next few weeks and I’ll probably post a blog post here and there.
I’d like to thank the entire Subtext team for all their contributions. This release probably contains the most diversity of patches and commits of all our releases with lots of new people pitching in to help.
I saw a recent Twitter thread discussing the arrogance of Steve Jobs. One person (ok, it was my buddy Rob) postulated that it was this very arrogance that led Apple to their successes.
I suppose it’s quite possible that it had a factor, but I tend to think Steve Job’s vision and drive were much bigger factors.
This idea is a reflection of a pervasive belief out there that arrogance is excusable, perhaps even acceptable and admirable in successful people and institutions. In contrast, I think we’d all agree that that arrogance is universally detestable in unsuccessful people.
But is arrogance necessary for success? I certainly don’t think so. I think there’s an alternative characteristic that can lead to just as much success.
Joy.
My example here is the most successful national soccer team ever, Brazil. They’ve won the most world cups of any team and yet the one word you’d be hard pressed to find anyone using to describe them is “Arrogant.” (Yes, I know that many from Argentina would disagree, but this is the perception out there) ;)
Instead, the word often associated with them is “Joy.” When Brazil plays, their joy for the beautiful game is so infectious you can’t help but share in the joy when they win. Heck, even as you’re grumbling about your own team losing to them, it’s hard not to join in the Samba spirit (again, unless you’re from Argentina).
This is a team that has been incredibly successful over the years and arrogance was unnecessary.
I think there are probably many examples in the technology and business world we could point to where incredible success and visionary leadership came from a joy in the work they do rather than arrogance. Have any examples for me? Leave them in the comments.
The World Cup starts in 6 days! I’ll try not to make all my posts soccer themed if I can help it. :)
The June issue (also in pdf) of the online PragPub magazine, published by the Pragmatic Bookshelf has two articles on ASP.NET MVC.
The first is called Agile Microsoft and is an introduction to ASP.NET MVC geared towards those who’ve never seen it. It’s nice seeing ASP.NET MVC featured in this magazine which in its own words tends to cater to a non-Microsoft crowd.
To some developers, Microsoft’s technologies are a given, the river they swim in. To others, not using Microsoft’s tools is the default. PragPub being an open source- and Agile-friendly kind of magazine, we tend to connect with the latter group.
So when we get an article titled “Agile Microsoft,” we are naturally intrigued. And we think you’ll also be intrigued by Jonathan McCracken’s introduction toASP.NET MVC, a framework that some have called “Rails for .NET.”
The second article is an interview with me entitled “Why ASP.NET MVC?” where I ramble on about how if wandering the halls of Microsoft doesn’t get you tossed out by security, it might land you a great job, as well as ASP.NET MVC, TDD, and Open Source Software.
Something I found interesting was that the person who interviewed me was Michael Swaine who co-wrote the book, Fire in the Valley, that the movie Pirates of Silicon Valley (no Jonny Depp in this one) was based on. The movie (and book) covers the rise of the computer industry and Steve Jobs, Bill Gates, among others.