Perfectionist Routing in ASP.NET MVC

I’m not one to accept /{ControllerName}/{ActionName} for my routes. Like a few members of the Stack Exchange team, I’m far too anal retentive about my routes to let Microsoft just handle it for me.

To this end, I use the excellent Attribute Routing project which is also available on NuGet: just type Install-Package AttributeRouting into the Package Manager and you’re ready to decorate your methods with route attributes like this:

[GET("some-action/{id}")]
public ActionResult SomeActionMethod(int id)
{
	return View();
}

 

A lot more than this is possible; for more details check out the AttributeRouting project wiki. Another nice feature during development time is the additional route “~/routes.axd” which shows you, in order, all the routes registered in your application (not just those registered by attributes) and gives you a lot of information that’s very helpful when debugging a routing problem.

All the benefits of attribute based routing aside, the problem quickly becomes that pesky default route. If you accidentally misspell a controller or action name in an ActionLink or other helper, you will get a URL that uses that default path due to this entry in the routes configuration in the Global.asax.cs:

routes.MapRoute(
	"Default", // Route name
	"{controller}/{action}/{id}", // URL with parameters
	new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

 

I don’t want my ActionLinks to use this default route. If it does, they’re wrong! I want to find out through an exception that I can easily detect during development, not by silently outputting a route that doesn’t work.

Read more »

Configuring Hudson/Jenkins to parse MSBuild output

When I started with continuous integration, I used CruiseControl.NET, but the XML configuration quickly got to be really tedious.

It didn’t take me long to switch to Hudson CI.  It’s free, and it’s easily managed through an intuitive web interface. Not that I can’t grok XML configuration files; I’d just rather be spending my time building things instead of figuring out how to get them built.

For a primer on how to use Hudson CI for .NET projects, take a look at Getting Started With CI Using Hudson For Your .NET Projects by Bob Cravens, or Continuous Integration with Hudson and .NET

The only problem is Hudson is Java-based, so it’s not exactly plug-n-play when it comes to .NET, MSBuild, and Visual Studio. Particularly, when a build failed, I would have to scan through hundreds of lines looking for the cause of the error, which is difficult to do with CTRL-F when this line is completely normal:

Compile complete -- 0 errors, 0 warnings
 

What is needed is the Log Parser Plugin (link includes formatting rules), which allows you to define regular expressions that determine how to interpret the lines of content in the MSBuild output, so that warnings and errors can be called out in different colors the same way that Visual Studio does. This plugin can be installed through Hudson’s built-in plugin manager, but you have to configure it yourself.

Read more »

Loading external resources without killing ASP.NET

If you run an ASP.NET website with any non-trivial amount of traffic, the last thing you want to do is try to load an external resource with a web request. Even if you cache it, you’ve taken on that external source as a dependency to your system, which means that your website is only as reliable as the external source you depend on.

The primary strategy I’ve seen to cope with this is to request the data from the remote service on the first request from the web tier, cache it locally, and then have a background process periodically refresh that cache so that subsequent requests can use locally cached data.

Even with this background-updated cache, eventually the external resource will suffer some sort of issue. The data in the cache grows old and is invalidated, and then the web tier starts requesting the data again, except now, 100 different requests try to open 100 different connections to the remote service to get the exact same data, because either they all fail or none of them can complete quickly enough to store the cache item for the other threads to use. The Thread Pool fills up, and ASP.NET hangs its head and gives up.

The Solution

Let’s assume that we are talking about a current weather tease that is a small part of a very large page, and that all our current weather information for the end-user’s zip code comes to us from an external provider.

So how do we avoid this mess? We can do it quite handily with a little NServiceBus and jQuery.

Read more »

Wanted: C# Property Initializers

I love to write code and I’m a great typist, but I hate typing if it’s not necessary. I’m a big fan of syntactical sugar and I think it’s high time C# got some more of it.

By now we’re all used to seeing this:

public string MyProperty { get; set; }

This eliminates the need to separately declare a private member variable and public property, because the compiler takes care of it for you.

What it doesn’t do is give you the option to set the initial value, like you could with a private member variable. Instead we have to do this:

public class MyClass
{
    public string MyProperty { get; set; }

    public MyClass()
    {
        MyProperty = "initial value";
    }
}

This really becomes more of a pain point now that I have delved into NServiceBus and RavenDB. With NServiceBus, I create a lot of message classes, and when the message includes a collection, it’s usually a good idea to initialize the empty collection so that I don’t get annoying null reference exceptions when I try to use them. The same is true of RavenDB when creating objects with collections to persist to the document store.

What if we could do this?

public string MyString { get; set; default "initial value"; }

public List<int> MyList { get; set; default new List<int>(); }

It would personally save me a LOT of time.

Destroying Security by Increasing Security

I have a friend.  Let’s call him “Steve”.

Steve was recently complaining to me about the password requirements imposed on him by Corporate IT.  He was using all sorts of words to describe them.  The only one suitable for reprinting was “stupid”.  They went downhill from there rather quickly.

Here are the password requirements Steve has to live with:

  • Must contain at least one uppercase letter A-Z.
  • Must contain at least one lowercase letter a-z.
  • Must contain at least one numeral 0-9.
  • Must contain at least one special character
  • Must be longer than 6 characters. (So >= 7)
  • Must be shorter than 9 characters. (So…7 or 8, but not 9)
  • Must begin and end with an alpha character A-Z or a-z.
  • The change periods (how often you must reset) vary.
  • You may not use any password you have used in the last year.

Seriously, did they just check every available box in the security setup? They may think they’re making things more secure, but in fact, the addition of all these options, especially with the addition of the very restrictive length requirement (7 or 8 characters, really?) conspires to drastically reduce security.

It reminded me a lot of this XKCD comic:

When you take social psychology into account, you can pretty much bet the farm on the following:

  • The requirements to change passwords several times a year and never repeat passwords in one year means that the month and date have to be in there.At the time of this writing, it is November 2011, so if I were trying to break a password on this system I could be reasonably sure that the password contains either 1111, 1011, 1110, 0911, 1109. That’s 5 possibilities.
  • It’s pretty safe to assume the date-based string of 4 characters will appear at the end of the password, but the fact that an alpha is required at the end means users will back it up one character. Therefore the password probably fits the regex [0-9]{4}[A-Za-z]$. The addition of the letter (26 * 2 for caps) possibilities means there are only 26*2*5 = 260 likely possibilities for the last 5 characters of the password.
  • If we assume 8 character passwords (would be stronger than 7 after all) then there are 3 characters left. It wouldn’t be ridiculous to assume:
    • First character caps: 26 possibilities
    • Second character lowercase: 26 possibilities
    • Third character a symbol easily reachable from a Shift+NumberKey sequence (there are 10) plus I’ll throw in a few more for good measure that are accessible by the right pinky finger.  Let’s say 20 possibilities.
    • Total possibilities for the first 3 chars = 26 * 26 * 20 = 13,520
  • Total likely passwords to attempt = 13,250 * 260 = 3,515,200.

3.5 million possibilities.  Using XKCD’s assumption of 1000 guesses/second, that’s less than an hour! I sure hope they have some lockout routines on top of that password policy. Considering that they must have checked every box, I suppose I can assume they did.

You may disagree with my math or my assumptions, but that the point is that adding additional security requirements doesn’t always increase security. So get it out of your head that your users are going to pick truly random passwords and think about how they are likely to act before you consider your system to be secure.

Robust 3rd Party Integrations with NServiceBus

A common question about NServiceBus is how to use it to integrate with an external partner. The requirements usually go something like this:

  • The third party will contact us via a web service, passing us a transaction identifier and a collection of fields.
  • If we successfully receive the message in the web service, we respond with a HTTP 200 OK status code.  If they do not receive the acknowledgement, they will assume a failure and attempt to retry the web service later.
  • Once we receive the message from the third party, we need to distribute (think publish) the contents of the message to more than one internal process, each of which are completely independent of each other.
  • We need to logically receive each message once and only once. In other words, it would be a “Very Bad Thing” for one of the internal subscribing processes to receive the same notification more than once.

This was most recently asked in this StackOverflow question, where it became difficult to explain more within the 600 character comment limit. The best explanation is example code, so here it is.

Read more »

Hidden iOS URL Keyboard Gem

For a long time I thought that the addition of a “.com” button on the iOS keyboard was a fantastic idea.  But what about .net, .org, and .edu domains?  Where’s the love for them?

I got to thinking, wouldn’t it be awesome if you could hover over the .com button and get a popup with options for the other common top-level domains?

Turns out the Apple engineers were way ahead of me.  Give it a shot sometime!

On my iPad (set to English/US keyboard layout of course) hovering over the .com button gives me additional options for .net, .org, .us, and .edu.  It does make me wonder if I would get something like .co.uk if I had a British keyboard setting.

What you apparently can NOT do is take a screenshot with the popup menu activated.

System.Security.Cryptography and Thread Safety

Are you experiencing either of these exceptions?

System.Security.Cryptography.CryptographicException
Padding is invalid and cannot be removed.

System.IndexOutOfRangeException
Index was outside the bounds of the array.

System.IndexOutOfRangeException
Probable I/O race condition detected while copying memory. The I/O package is not thread safe by default. In multithreaded applications, a stream must be accessed in a thread-safe way, such as a thread-safe wrapper returned by TextReader’s or TextWriter’s Synchronized methods. This also applies to classes like StreamWriter and StreamReader.

Well at least the last one is descriptive, but that is the LEAST likely to occur.

If you’re seeing any of these exceptions, there’s a good chance you’ve run afoul of a secret of the System.Cryptography namespace.  Almost nothing is thread safe.

It’s an easy error to make. We know encryption is processor intensive, and it seems like it would be smart to incur the costs of setting up ICryptoTransform objects for encryptors and decryptors once and then store them in a static variable. Any state they might share would seem to be reference data like keys and salt and init vectors, so as long as we use a new CryptoStream for each operation, what could go wrong?

Well, lots.

Internally, the implementations of ICryptoTransform (and I assume other objects) use objects from the System.IO namespace like buffers and streams that we would never think of sharing between threads, but it’s hard to know that from a simple call to ICryptoTransform.TransformBlock().

So, if you run into any of the exceptions above, try either creating your System.Cryptography objects each time you need them, or mark them with the ThreadStaticAttribute.  Remember that with [ThreadStatic], a static initializer will not execute for each thread, so check it for null before you use it, then initialize if null.

Stuck between Netflix and a hard place

There are two types of people in the world right now: those who are angry at Netflix and those who don’t have Netflix.

Like everyone else, I received the email yesterday notifying me that as of September 1, 2011, my $10 Netflix plan that includes 1 DVD at a time and online unlimited streaming will be discontinued. Instead, they offer separate plans for DVDs and for streaming.  1 DVD at a time will now cost $8, and unlimited streaming will now also cost $8.  There is no discount for bundling, so if I want to continue the same level of service, it will now cost me $16 per month.

It’s not the money that bothers me. Prices were bound to go up.  Maybe this is a pretty severe jump all at once, but it’s not completely unexpected.

What bothers me is the false choice it represents. If money does indeed talk (and I believe it does) then Netflix is asking me to choose from these options:

  1. I like getting DVDs from you, but I don’t care for your streaming service. Please take my money and keep the DVDs coming.
  2. I love your streaming service, but DVDs in the mail is so 2003. Please take my money and let me stream to my heart’s content, but don’t make me walk out to the mailbox.
  3. I like DVDs and I also like streaming, and I’m willing to pay more money for both.
  4. Netflix, you suck. Cancel my subscription.

I don’t believe that any of these four options correctly captures my real intent:

I would be willing to pay $16 per month, maybe even more, just for the streaming service, provided that the streaming selection didn’t suck.

Read more »