code comments edit

UPDATE: A reader named Matthias pointed out there is a flaw in my code. Thanks Matthias! I’ve corrected it in my GitHub Repository. The code would break if your attribute had an array property or constructor argument.

I’ve been working on a lovely little prototype recently but ran into a problem where my code receives a collection of attributes and needs to change them in some way and then pass the changed collection along to another method that consumes the collection.

reflection

I  want to avoid changing the attributes directly, because when you use reflection to retrieve attributes, those attributes may be cached by the framework. So changing an attribute is not a safe operation as you may be changing the attribute for everyone else who tries to retrieve them.

What I really wanted to do is create a copy of all these attributes, and pass the collection of copied attributes along. But how do I do that?

CustomAttributeData

Brad Wilson and David Ebbo to the rescue! In a game of geek telephone, David told Brad a while back, who then recently told me, about a little class in the framework called CustomAttributeData.

This class takes advantage of a feature of the framework known as a Reflection-Only context. This allows you to examine an assembly without instantiating any of its types. This is useful, for example, if you need to examine an assembly compiled against a different version of the framework or a different platform.

Copying an Attribute

As you’ll find out, it’s also useful when you need to copy an attribute. This might raise the question in your head, “if you have an existing attribute instance, why can’t you just copy it?” The problem is that a given attribute might not have a default constructor. So then you’re left with the challenge of figuring out how to populate the parameters of a constructor from an existing instance of an attribute. Let’s look at a sample attribute.

[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class SomethingAttribute : Attribute {
  public SomethingAttribute(string readOnlyProperty) {
      ReadOnlyProperty = readOnlyProperty;
  }
  public string ReadOnlyProperty { get; private set; }
  public string NamedProperty { get; set; }
  public string NamedField;
}

And here’s an example of this attribute applied to a class a couple of times.

[Something("ROVal1", NamedProperty = "NVal1", NamedField = "Val1")]
[Something("ROVal2", NamedProperty = "NVal2", NamedField = "Val2")]
public class Character {
}

Given an instance of this attribute, I might be able to figure out how the constructor argument should be populated by assuming a convention of using the property with the same name as the argument. But what if the attribute had a constructor argument that had no corresponding property? Keep in mind, I want this to work with arbitrary attributes, not just ones that I wrote.

CustomAttributeData saves the day!

This is where CustomAttributeData comes into play. An instance of this class tells you everything you need to know about the attribute and how to construct it. It provides access to the constructor, the constructor parameters, and the named parameters used to declare the attribute.

Let’s look at a method that will create an attribute instance given an instance of CustomAttributeData.

public static Attribute CreateAttribute(this CustomAttributeData data){
  var arguments = from arg in data.ConstructorArguments
                    select arg.Value;

  var attribute = data.Constructor.Invoke(arguments.ToArray())     as Attribute;

  foreach (var namedArgument in data.NamedArguments) {
    var propertyInfo = namedArgument.MemberInfo as PropertyInfo;
    if (propertyInfo != null) {
      propertyInfo.SetValue(attribute, namedArgument.TypedValue.Value, null);
    }
    else {
      var fieldInfo = namedArgument.MemberInfo as FieldInfo;
      if (fieldInfo != null) {
        fieldInfo.SetValue(attribute, namedArgument.TypedValue.Value);
      }
    }
  }

  return attribute;
}

The code sample demonstrates how we use the information within the CustomAttributeData instance to figure out how to create an instance of the attribute described by the data.

So how did we get the CustomAttributeData instance in the first place? That’s pretty easy, we called the CustomAttributeData.GetCustomAttributes() method. With these pieces in hand, it’s pretty straightforward now to copy the attributes on a type or member. Here’s a set of extension methods I wrote to do just that.

NOTE: The following code does not handle array properties and constructor arguments correctly. Check out my repository for the correct code.

public static IEnumerable<Attribute> GetCustomAttributesCopy(this Type type) {
  return CustomAttributeData.GetCustomAttributes(type).CreateAttributes();
}

public static IEnumerable<Attribute> GetCustomAttributesCopy(    this Assembly assembly) {
  return CustomAttributeData.GetCustomAttributes(assembly).CreateAttributes();
}

public static IEnumerable<Attribute> GetCustomAttributesCopy(    this MemberInfo memberInfo) {
  return CustomAttributeData.GetCustomAttributes(memberInfo).CreateAttributes();
}

public static IEnumerable<Attribute> CreateAttributes(    this IEnumerable<CustomAttributeData> attributesData) {
  return from attributeData in attributesData
          select attributeData.CreateAttribute();
}

And here’s a bit of code I wrote in a console application to demonstrate the usage.

foreach (var instance in typeof(Character).GetCustomAttributesCopy()) {
  var somethingAttribute = instance as SomethingAttribute;
  Console.WriteLine("ReadOnlyProperty: " + somethingAttribute.ReadOnlyProperty);
  Console.WriteLine("NamedProperty: " + somethingAttribute.NamedProperty);
  Console.WriteLine("NamedField: " + somethingAttribute.NamedField);
}

And there you have it, I can grab the attributes from a type and produce a copy of those attributes.

With this out of the way, I can hopefully continue with my original prototype which led me down this rabbit hole in the first place. It always seems to happen this way, where I start a blog post, only to start writing a blog post to support that blog post, and then a blog post to support that one. Much like a dream within a dream within a dream. ;)

asp.net, asp.net mvc, code comments edit

In ASP.NET MVC 3 Preview 1, we introduced some syntactic sugar for creating and accessing view data using new dynamic properties.

sugarSugar, it’s not just for breakfast.

Within a controller action, the ViewModel property of Controller allows setting and accessing view data via property accessors that are resolved dynamically at runtime. From within a view, the View property provides the same thing (see the addendum at the bottom of this post for why these property names do not match).

Disclaimer

This blog post talks about ASP.NET MVC 3 Preview 1, which is a pre-release version. Specific technical details may change before the final release of MVC 3. This release is designed to elicit feedback on features with enough time to make meaningful changes before MVC 3 ships, so please comment on this blog post if you have comments.

Let’s take a look at the old way and the new way of doing this:

The old way

The following is some controller code that adds a string to the view data.

public ActionResult Index() {
  ViewData["Message"] = "Some Message";
  return View();
}

The following is code within a view that accesses the view data we supplied in the controller action.

<h1><%: ViewData["Message"] %></h1>

The new way

This time around, we use the ViewModel property which is typed as dynamic. We use it like we would any property.

public ActionResult Index() {
  ViewModel.Message = "Some Message";
  return View();
}

And we reference it in a Razor view. Note that this also works in a WebForms View too.

<h1>@View.Message</h1>

Note that View.Message is equivalent to View["Message"].

Going beyond properties

However, what might not be clear to everyone is that you can also store and call methods using the same approach. Just for fun, I wrote an example of doing this.

In the controller, I defined a lambda expression that takes in an index and two strings. It returns the first string if the index is even, and the second string if the index is odd. It’s very simple.

The next thing I do is assign that lambda to the Cycle property of ViewModel, which is created on the spot since ViewModel is dynamic.

public ActionResult Index() {
  ViewModel.Message = "Welcome to ASP.NET MVC!";

  Func<int, string, string, string> cycleMethod = 
    (index, even, odd) => index % 2 == 0 ? even : odd;
  ViewModel.Cycle = cycleMethod;

  return View();
}

Now, I can dynamically call that method from my view.

<table>
@for (var i = 0; i < 10; i++) {
    <tr class="@View.Cycle(i, "even-css", "odd-css")">
        <td>@i</td>
    </tr>
}
</table>

As a fan of dynamic languages, I find this technique to be pretty slick. :)

The point of this blog post was to show that this is possible, but it raises the question, “why would anyone want to do this over writing a custom helper method?”

Very good question! Right now, it’s mostly a curiosity to me, but I can imagine cases where this might come in handy. However, if you re-use such view functionality or really need Intellisense, I’d highly recommend making it a helper method. I think this approach works well for rapid prototyping and maybe for one time use helper functions.

Perhaps you’ll find even better uses I didn’t think of at all.

Addendum: The Property name mismatch

Earlier in this post I mentioned the mismatch between property names, ViewModel vs View. I also talked about this in a video I recorded for MvcConf on MVC 3 Preview 1. Originally, we wanted to pick a nice terse name for this property so when referencing it in the view, there is minimal noise. We liked the property View for this purpose and implemented it for our view page first.

But when we went to port this property over to the Controller, we realized it wouldn’t work. Anyone care to guess why? Yep, that’s right. Controller already has a method named View so it can’t also have a property named the same thing. So we called it ViewModel for the time being and figured we’d change it once we came up with a better name.

So far, we haven’t come up with a better name that’s both short and descriptive. And before you suggest it, the acronym of “View Data” is not an option.

If you have a better name, do suggest it. :)

Addendum 2: Unit Testing

Someone on Twitter asked me how you would unit test this action method. Here’s an example of a unit tests that shows you can simply call this dynamic method directly from within a unit test (see the act section below).

[TestMethod]
public void CanCallCycle() {
  // arrange
  var controller = new HomeController();
  controller.Index();

  // act
  string even = controller.ViewModel.Cycle(0, "even", "odd");

  // assert
  Assert.AreEqual("even", even);
}

Tags: aspnetmvc, dynamic, viewdata

asp.net, code, asp.net mvc comments edit

UPDATE: This post is a out of date. We recently released the Release Candidate for ASP.NET MVC 3.

Feels like just yesterday that we released ASP.NET MVC 2 to the world and here I am already talking about an early preview. In a way, we’re right on schedule. It was almost exactly a year ago that we released Preview 1 of ASP.NET MVC 2.

Today I’m happy to announce that ASP.NET MVC 3 Preview 1 is available for download. Give it a try out and let us know what you think. Some key notes before you give it a whirl:

  • ASP.NET MVC 3 Preview 1 tooling requires Visual Studio 2010
  • ASP.NET MVC 3 Preview 1 runtime requires the ASP.NET 4 runtime

As usual, to find out what’s in this release, check out the release notes. Also at the recent MVCConf, a virtual conference about ASP.NET MVC, I recorded a talk that provided a sneak peek at ASP.NET MVC 3 Preview 1. The audio quality isn’t great, but I do demo some of the key new features so be sure to check it out.

So what’s in this release that I’m excited about? Here’s a small sampling:

  • Razor View Engine which ScottGu wrote about recently. Note that for Preview 1, we only support the C# version (CSHTML). IN later previews, we will add support for the VB.NET version (VBHTML). Also, Intellisense support for Razor syntax in Visual Studio 2010 will be released later.
  • Dependency Injection hooks using service locator interface. Brad Wilson should have a few blog posts on this over the next few days.
  • Support for .NET 4 Data Annotation and Validation attributes.
  • Add View dialog support for multiple view engines including custom view engines.
  • Global Action Filters

In the next few days you should see more details about each of these areas start to show up in various blog posts. I’ll try to keep this blog post updated with relevant blog posts so you can find them all. Enjoy!

asp.net mvc, asp.net, code comments edit

I wanted to confirm something about how to upload a file or set of files with ASP.NET MVC and the first search result for the phrase “uploading a file with asp.net mvc” is Scott Hanselman’s blog post on the topic.

His blog post is very thorough and helps provide a great understanding of what’s happening under the hood. The only complaint I have is that the code could be much simpler since we’ve made improvements to the ASP.NET MVC 2. I write this blog post in the quixotic hopes of knocking his post from the #1 spot.

Uploading a single file

Let’s start with the view. Here’s a form that will post back to the current action.

<form action="" method="post" enctype="multipart/form-data">
  
  <label for="file">Filename:</label>
  <input type="file" name="file" id="file" />

  <input type="submit" />
</form>

Here’s the action method that this view will post to which saves the file into a directory in the App_Data folder named “uploads”.

[HttpPost]
public ActionResult Index(HttpPostedFileBase file) {
            
  if (file.ContentLength > 0) {
    var fileName = Path.GetFileName(file.FileName);
    var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
    file.SaveAs(path);
  }
            
  return RedirectToAction("Index");
}

Notice that the argument to the action method is an instance of HttpPostedFileBase. ASP.NET MVC 2 introduces a new value providers feature which I’ve covered before.

Whereas model binders are used to bind incoming data to an object model, value providers provide an abstraction for the incoming data itself.

In this case, there’s a default value provider called the HttpFileCollectionValueProvider which supplies the uploaded files to the model binder.Also notice that the argument name, file, is the same name as the name of the file input. This is important for the model binder to match up the uploaded file to the action method argument.

Uploading multiple files

In this scenario, we want to upload a set of files. We can simply have multiple file inputs all with the same name.

<form action="" method="post" enctype="multipart/form-data">
    
  <label for="file1">Filename:</label>
  <input type="file" name="files" id="file1" />
  
  <label for="file2">Filename:</label>
  <input type="file" name="files" id="file2" />

  <input type="submit"  />
</form>

Now, we just tweak our controller action to accept an IEnumerable of HttpPostedFileBase instances. Once again, notice that the argument name matches the name of the file inputs.

[HttpPost]
public ActionResult Index(IEnumerable<HttpPostedFileBase> files) {
  foreach (var file in files) {
    if (file.ContentLength > 0) {
      var fileName = Path.GetFileName(file.FileName);
      var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
      file.SaveAs(path);
    }
  }
  return RedirectToAction("Index");
}

Yes, it’s that easy. :)

Tags: aspnetmvc, upload

asp.net, asp.net mvc, razor comments edit

UPDATE: Check out my Razor View Syntax Quick Reference for a nice quick reference to Razor.

There’s an old saying, “Good things come to those who wait.” I remember when I first joined the ASP.NET MVC project, I (and many customers) wanted to include a new streamlined custom view engine. Unfortunately at the time, it wasn’t in the card since we had higher priority features to implement.

Well the time for a new view engine has finally come as announced by Scott Guthrie in this very detailed blog post.

Photo by "clix"
http://www.sxc.hu/photo/955098

While I’m very excited about the new streamlined syntax, there’s a lot under the hood I’m also excited about.

Andrew Nurse, who writes the parser for the Razor syntax, provides more under-the-hood details in this blog post. Our plan for the next version of ASP.NET MVC is to make this the new default view engine, but for backwards compatibility we’ll keep the existing WebForm based view engine.

As part of that work, we’re also focusing on making sure ASP.NET MVC tooling supports any view engine. In ScottGu’s blog post, if you look carefully, you’ll see Spark listed in the view engines drop down in the Add View dialog. We’ll make sure it’s trivially easy to add Spark, Haml, whatever, to an ASP.NET MVC project. :)

Going back to Razor, one benefit that I look forward to is that unlike an ASPX page, it’s possible to fully compile a CSHTML page without requiring the ASP.NET pipeline. So while you can allow views to be compiled via the ASP.NET runtime, it may be possible to fully compile a site using T4 for example. A lot of cool options are opened up by a cleanly implemented parser.

In the past several months, our team has been working with other teams around the company to take a more holistic view of the challenges developing web applications. ScottGu recently blogged about the results of some of this work:

  • SQLCE 4 – Medium trust x-copy deployable database for ASP.NET.
  • IIS Express – A replacement for Cassini that does the right thing.

The good news is there’s a lot more coming! In some cases, we had to knock some heads together (our heads and the heads of other teams) to drive focus on what developers really want and need rather than too much pie in the sky architectural astronomy.

I look forward to talking more about what I’ve been working on when the time is right. :)

subtext, personal comments edit

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.

cody-phil-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.

hiking-trip

Funny how all that “hiking” works up an appetite.

cody-burger

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.

DotNetLicense

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.

code comments edit

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. :)

code comments edit

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.

subtext comments edit

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.

elephant-skinIn 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.

comments edit

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.subtext-dashboardThe 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.

personal comments edit

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.

pele
pic

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. :)

asp.net mvc, personal, open source comments edit

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.

code comments edit

A while ago I was talking with my manager at the time about traits that we value in a Program Manager. He related an anecdote about an interview he gave where it became clear that the candidate did not deal well with ambiguity.

This is an important trait for nearly every job, but especially for PMs as projects can often change on a dime and it’s important understand how to make progress amidst ambiguity and eventually drive towards resolving ambiguity.

Lately, I’ve been asking myself the question, doesn’t this apply just as much to software?

One of the most frustrating aspects of software today is that it doesn’t deal well with ambiguity. You could take the most well crafted robust pieces of software, and a cosmic ray could flip one bit in memory and potentially take the whole thing down.

The most common case of this fragility that we experience is in the form of breaking changes. Pretty much all applications have dependencies on other libraries or frameworks. One little breaking change in such a library or framework and upgrading that dependency will quickly take down your application.

Someday, I’d love to see software that really did deal well with ambiguity.

For example, lets take imagine a situation where a call to a method which has changed its signature wouldn’t result in a failure but would be resolved automatically.

In the .NET world, we have something close with the concept of assembly binding redirection, which allow you to redirect calls compiled against one version of an assembly to another. This is great if none of the signatures of existing methods have changed. I can imagine taking this further and allowing application developers to apply redirection to method calls account for such changes. In many cases, the method itself that changed could indicate how to perform this redirection. In the simplest case, you simply keep the old method and have it call the new method.

More challenging is the case where the semantics of the call itself have changed. Perhaps the signature hasn’t changed, but the behavior has changed in subtle ways that could break existing applications.

In the near future, I think it would be interesting to look at ways that software that introduce such breaks could also provide hints at how to resolve the breaks. Perhaps code contracts or other pre conditions could look at how the method is called and in cases where it would be broken, attempt to resolve it.

Perhaps in the further future, a promising approach would move away from programming with objects and functions and look at building software using autonomous software agents that communicate with each other via messages as the primary building block of programs.

In theory, autonomous agents are aware of their environment and flexible enough to deal with fuzzy situations and make decisions without human interaction. In other words, they know how to deal with some level of ambiguity.

I imagine that even in those cases, situations would arise that the software couldn’t handle without human involvement, but hey, that happens today even with humans. I occasionally run into situations I’m not sure how to resolve and I enlist the help of my manager and co-workers to get to a resolution. Over time, agents should be able to employ similar techniques of enlisting other agents in making such decisions.

Thus when an agent is upgraded, ideally the entire system continues to function without coming to a screeching halt. Perhaps there’s a brief period where the system’s performance is slightly degraded as all the agents learn about the newly upgraded agent and verify their assumptions, etc. But overall, the system deals with the changes and moves on.

A boy can dream, eh? In the meanwhile, if reducing the tax of backwards compatibility is the goal, there are other avenues to look at. For example, by you could apply isolation using virtualization so that an application always runs in the environment it was designed for, thus removing any need for dealing with ambiguity (apart from killer cosmic rays).

In any case, I’m excited to see what new approaches will appear over the next few decades in this area that I can’t even begin to anticipate.

personal comments edit

The last time I wrote about one of my hiking adventures, it started off great, but really didn’t end well. But I survived, so on that scale, yes it did end well! It’s a matter of perspective.

On Saturday, I went on my first hike of the spring to Lake Serene and Bridal Veil Falls. This hike is really two hikes in one. The main destination is Lake Serene, but there’s an absolutely wonderful half mile (1 mile round trip) side trip to the Bridal Veil Falls on the way to Lake Serene.

The trail starts in the small town of Index in the county of HomeController (sorry, I couldn’t resist). The entire trail is lush with greenery as you would expect in the pacific northwest. All along the trail are many little waterfalls and river crossings like the one seen here.

IMG_0346

The early part of the hike is dominated by moss covered trees and bushes. Higher up there’s less moss, but just as many trees.

IMG_0359Nearly two miles in, there’s a juncture with a sign pointing to the right towards Bridal Veil Falls. There’s a juncture before this one without the sign, don’t take that one, take this one.

The roar of the falls served as our guide through the series of switchbacks leading us to a grand view.

IMG_0360

There are two viewing platforms, both with great views of the falls.

The trail is well marked and easy to follow, though it wasn’t without its occasional obstacle. Nothing a strong man like myself can’t handle though.

IMG_0372 As we got closer to the lake, we captured glimpses of snow capped mountains jutting into the sky. Near the end of the trail, we rounded a bend and were greeted with the sight of a calm lake nestled in a snow covered valley surrounded by jagged peaks. The lake lives up to its name.

IMG_0376We followed a little trail along the lake to a large rock face where we were able to get a better view of the trail. There just happened to be a large group of friends already there, breaking the sense of solitude. IMG_0386But who are we to blame them, the view was beautiful despite the clouds and rain rolling in right as we got there.

IMG_0392If you live in the Seattle or Bellevue area, I highly recommend this hike. One member of the large group told us that he did the same hike a month ago and the lake was still frozen over and they sat back and enjoyed the dramatic site of constant avalanches on the other side of the lake. We didn’t get the opportunity to witness any.

tech comments edit

Here’s a handy tip I just recently learned from the new intern on our team (see, you can learn something from anyone on any given day). I’ve long known you could access your local drives from a remote machine.

For example, start up a remote desktop dialog.

Remote Desktop Dialog

Then expand the dialog by clicking on Options, then check the Local**Resources tab.

Remote Desktop Local Resources Options

Make sure Clipboard is checked, and then hit the More… button.

Remote Desktop Drives

Now you can select a local disk to be shared with the remote machine. For example, in this case I selected my C: drive.

Local Drive shared on Remote DesktopAs you can see in the screenshot, the file explorer has another drive named “C on HAACKBOOK” which can be used to copy files back and forth from my local machine to the remote machine.

But here’s the part I didn’t know. Let’s take a look at the desktop of my remote machine, which has a text file named info.txt.

Remote Desktop

One way I can get that file to my local machine is to copy it to the mapped drive we saw in the previous screenshot.

Or, I can simply drag and drop the info.txt from my remote desktop machine to a folder on my local machine.

stuff

So all this time, I had no idea cut and paste operations for files work across remote desktop. This may be obvious for many of you, but it wasn’t to me. :)

asp.net, code comments edit

ASP.NET 4 introduces a few new extensibility APIs that live the hermit lifestyle away from the public eye. They’re not exactly hidden - they are well documented on MSDN - but they aren’t well publicized. It’s about time we shine a spotlight on them.

PreApplicationStartMethodAttribute

This new attribute allows you to have code run way early in the ASP.NET pipeline as an application starts up. I mean way early, even before Application_Start.

This happens to also be before code in your App_code folder (assuming you have any code in there) has been compiled.

To use this attribute, create a class library and add this attribute as an assembly level attribute. A common place to add this would be in the AssemblyInfo.cs class within the Properties folder.

Here’s an example:

[assembly: PreApplicationStartMethod(
  typeof(SomeClassLib.Initializer), "Initialize")]

Note that I specified a type and a method. That method needs to be a public static void method with no arguments. Now, any ASP.NET website that references this assembly will call the Initialize method when the application is about to start, giving this method a chance to do perform some early initialization.

public static class Initializer
{
  public static void Initialize() { 
    // Whatever can we do here?
  }
}

The primary use of this feature is to enable tasks that can’t be done within Application_Start because it’s too late. For example, registering build providers and adding assembly references.

Which leads us to…

BuildProvider.RegisterBuildProvider

As you might guess, if one of the key scenarios for the previously mentioned feature is to allow registering build providers, well ASP.NET better darn well allow you to register them programmatically.

Prior to ASP.NET 4, the only way to register a custom build provider was via the <buildproviders> node within web.config. But now, you can register them programmatically via a call to the new BuildProvider.RegisterBuildProvider method.

BuildProvider.RegisterBuildProvider(".foo", typeof(MyBuildProvider));

Combining the PreApplicationStartMethodAttribute with this method call means that installing a build provider can be done in one step -simply reference the assembly with the build provider and the assembly can register it for you. Whereas before, you would have to reference the assembly and then muck around with web.config.

I think I speak for us all when I say “Yay! Less junk in my web.config trunk!”

BuildManager.AddReferencedAssembly

Another new method added in ASP.NET 4 allows adding an assembly to the application’s list of referenced assemblies. This is equivalent to adding an assembly to the <assemblies> section of web.config.

As you might guess, this comes in handy when registering a custom build provider. It allows you to programmatically add references to assemblies that may be needed by your build provider.

Oh, and it’s yet another way to reduce the size of your web.config file. Who doesn’t love that? :)

asp.net, asp.net mvc, code comments edit

One of my favorite features of ASP.NET MVC 2 is the support for client validation. I’ve covered a bit about validation in the following two posts:

However, one topic I haven’t covered is how validation works with globalization. A common example of this is when validating a number, the client validation should understand that users in the US enter periods as a decimal point, while users in Spain will use a comma.

For example, let’s assume I have a type with the RangeAttribute applied. In this case, I’m applying a range from 100 to 1000.

public class Product
{
    [Range(100, 1000)]
    public int QuantityInStock { get; set; }

    public decimal Cost { get; set; }
}

And in a strongly typed view, we have the following snippet.

<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm()) {%>

    <%: Html.LabelFor(model => model.QuantityInStock) %>
    <%: Html.TextBoxFor(model => model.QuantityInStock)%>
    <%: Html.ValidationMessageFor(model => model.QuantityInStock)%>

<% } %>

Don’t forget to reference the necessary ASP.NET MVC scripts. I’ve done it in the master page.

<script src="/Scripts/MicrosoftAjax.debug.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.debug.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcValidation.debug.js" type="text/javascript"></script>

Now, when I visit the form, type in 1,000 into the text field, and hit the TAB key, I get the following behavior.

valid-range

Note that there is no validation message because in the US, 1,000 == 1000 and is within the range. Now let’s see what happens when I type 1.000.

invalid-range

As we can see, that’s not within the range and we get an error message.

Fantastic! That’s exactly what I would expect, unless I was a Spaniard living in Spain (¡Hola mis amigos!).

In that case, I’d expect the opposite behavior. I’d expect 1,000 to be equivalent to 1 and thus not in the range, and I’d expect 1.000 to be 1000 and thus in the range, because in Spain (as in many European countries), the comma is the decimal separator.

Setting up Globalization for ASP.NET MVC 2

Well it turns out, we can make ASP.NET MVC support this. To demonstrate this, I’ll need to change my culture to es-ES. There are many blog posts that cover how to do this automatically based on the request culture. I’ll just set it in my Global.asax.cs file for demonstration purposes.

protected void Application_BeginRequest() {
  Thread.CurrentThread.CurrentCulture     = CultureInfo.CreateSpecificCulture("es-ES");
}

The next step is to add a call to the Ajax.GlobalizationScript helper method in my Site.master.

<head runat="server">
  <%: Ajax.GlobalizationScript() %>
  <script src="/Scripts/MicrosoftAjax.debug.js" type="text/javascript">
  </script>
  <script src="/Scripts/MicrosoftMvcAjax.debug.js" type="text/javascript">
  </script>
  <script src="/Scripts/MicrosoftMvcValidation.debug.js" type="text/javascript">
  </script>
</head>

What this will do is render a script tag pointing to a globalization script named according to the current locale and placed in scripts/globalization directory by convention. The idea is that you would place all the globalization scripts for each locale that you support in that directory. Here’s the output of that call.

<script type="text/javascript" src="~/Scripts/Globalization/es-ES.js">
</script>

As you can see, the script name is es-ES.js which matches the current locale that we set in Global.asax.cs. However, there’s something odd with that output. Do you see it? Notice that tilde in the src attribute? Uh oh! That there is a bona fide bug in ASP.NET MVC.

Not to worry though, there’s an easy workaround. Knowing how discriminating our ASP.NET MVC developers are, we knew that people would want to place these scripts in whatever directory they want. Thus we added a global override via the AjaxHelper.GlobalizationScriptPath property.

Even better, these scripts are now available on the CDN as of this morning (thanks to Stephen and his team for getting this done!), so you can specify the CDN as the default location. Here’s what I have in my Global.asax.cs.

protected void Application_Start()
{
  AjaxHelper.GlobalizationScriptPath =     "http://ajax.microsoft.com/ajax/4.0/1/globalization/";
            
  AreaRegistration.RegisterAllAreas();
  RegisterRoutes(RouteTable.Routes);
}

With that in place, everything now just works. Let’s try filling out the form again.

This time, 1,000 is not within the valid range because that’s equivalent to 1 in the es-ES locale.

invalid-range-es-ES

Meanwhile, 1.000 is within the valid range as that’s equivalent to 1,000.

valid-range-es-ES

So what are these scripts?

They are simply a JavaScript serialization of all the info within a CultureInfo object. So the information you can get on the server, you can now get on the client with these scripts.

In Web Forms, these scripts are emitted automatically by serializing the culture at runtime. However this approach doesn’t work for ASP.NET MVC.

One reason is that the scripts themselves changed from ASP.NET 3.5 to ASP.NET 4. ASP.NET MVC is built against the ASP.NET 4 version of these scripts. But since MVC 2 runs on both ASP.NET 3.5 and ASP.NET 4, we couldn’t rely on the script manager to emit the scripts for us as that would break when running on ASP.NET 3.5 which would emit the older version of these scripts.

As usual, I have very simple sample you can download to see the feature in action.

asp.net mvc, asp.net, code comments edit

The ASP.NET MVC2 templates feature is a pretty nice way to quickly scaffold objects at runtime. Be sure to read Brad Wilson’s fantastic series on this topic starting at ASP.NET MVC 2 Templates, Part 1: Introduction.

As great as this feature is, there is one template that’s conspicuously missing. ASP.NET MVC does not include a template for displaying a list of objects in a tabular format. Earlier today, ScottGu forwarded an email from Daniel Manes (what?! no blog! ;) with a question on how to accomplish this. Daniel had much of it implemented, but was trying to get over the last hurdle.

With Brad’s help, I was able to give him a boost over that hurdle. Let’s walk through the scenario.

First, we need a model.

zoolander

No, not that kind of model. Something more along the lines of a C# variety.

public class Book
{
    public int Id { get; set; }

    public string Title { get; set; }

    public string Author { get; set; }

    [DisplayName("Date Published")]
    public DateTime PublishDate { get; set; }
}

Great, now lets add a controller action to the default HomeController which will create a few books and pass them to a view.

public ActionResult Index()
{
    var books = new List<Book>
    {
        new Book { 
            Id = 1, 
            Title = "1984", 
            Author = "George Orwell", 
            PublishDate = DateTime.Now 
        },
        new Book { 
            Id = 2, 
            Title = "Fellowship of the Ring", 
            Author = "J.R.R. Tolkien", 
            PublishDate = DateTime.Now 
        },
        //...
    };
    return View(books);
}

Now we’ll create a strongly typed view we’ll use to display a list of such books.

<% @Page MasterPageFile="~/Views/Shared/Site.Master"
  Language="C#"
  Inherits="ViewPage<IEnumerable<TableTemplateWeb.Models.Book>>" %>

<asp:Content ContentPlaceHolderID="TitleContent" runat="server">
    Home Page
</asp:Content>

<asp:Content ContentPlaceHolderID="MainContent" runat="server">
    <h2>All Books</h2>
    <p>
        <%: Html.DisplayForModel("Table") %>
    </p>
</asp:Content>

If you run the code right now, you won’t get a very useful display. Also, notice that we pass in the string “Table” to the DisplayForModel method. That’s a hint to the template method which tells it, “Hey! If you see a template named ‘Table’, tell him he owes me money! Oh, and use it to render the model. Otherwise, if he’s not around fallback to your normal behavior.”

Since we don’t have a Table template yet, this code is effectively the same as if we didn’t pass anything to DisplayForModel.

What we need to do now is create the Table template. To do so, create a DisplayTemplates folder within the Views/Shared directory. Then right click on that folder and select Add | View.

This brings up the Add View dialog. Enter Table as the view name and make sure check Create a partial view. Also, check Create a strongly-typed view and type in IList as the View Data Class.

Add View
Dialog

When you click Add, you should see the new template in the DisplayTemplates folder like so.

solution
explorer

Here’s the code for the template. Note that there’s some code in here that I could refactor into a helper class in order to clean up the template a bit, but I wanted to show the full template code here in one shot.

<% @Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IList>" %>
<script runat="server">
  public static bool ShouldShow(ModelMetadata metadata,       ViewDataDictionary viewData) {
    return metadata.ShowForDisplay
      && metadata.ModelType != typeof(System.Data.EntityState)
      && !metadata.IsComplexType
      && !viewData.TemplateInfo.Visited(metadata);
  }
</script>
<%
  var properties = ModelMetadata.FromLambdaExpression(m => m[0], ViewData)
    .Properties
    .Where(pm => ShouldShow(pm, ViewData));
%>
<table>
  <tr>
    <% foreach(var property in properties) { %>        
    <th>
      <%= property.GetDisplayName() %>
    </th>
    <% } %>
  </tr>
    <% for(int i = 0; i < Model.Count; i++) {
    var itemMD = ModelMetadata.FromLambdaExpression(m => m[i], ViewData); %>
    <tr>
      <% foreach(var property in properties) { %>
      <td>
        <% var propertyMetadata = itemMD.Properties
              .Single(m => m.PropertyName == property.PropertyName); %>  
          <%= Html.DisplayFor(m => propertyMetadata.Model) %>
        </td>
      <% } %>
    </tr>
    <% } %>
</table>

Explanation {.clear}

There’s a lot going on in here, but I’ll try to walk through it bit by bit. If you’d rather skip this part and just take the code and run, I won’t hold it against you.

In the first section, we define a ShouldShow method which is pulled right out of the logic for our default Object template. You’ll notice there’s mention of System.Data.EntityState (defined in the System.Data.Entity.dll) which is used to filter out certain Entity Framework properties. If you aren’t using Entity Framework you can safely delete that line.You’ll know you don’t need that line if you aren’t referencing System.Data.Entity.dll which will cause this code to blow up like aluminum foil in a microwave.

In the next code block, we grab all the property ModelMetadata for the first item in the list. Remember, the current model in this template is a list, but we need the metadata for an item in this list, not the list itself. That’s why we have this odd bit of code here. Once we grab this metadata, we can iterate over it and display the column headers.

In the final block of code, we iterate over every item in the list and use this handy dandy FromLambdaExpression method to grab the ModelMetadata for an individual item.

Then we grab the property metadata for that item and iterate over that so that we can display each property in its own column. Notice that we call DisplayFor on each property rather than simply spitting out propertyMetadata.Model.

Usage

Now that you’ve created this Table.ascx template and placed it in the Shared/DisplayTemplates folder, it is available any time you’re using a display template to render a list. Simply supply a hint to use the table template. For example:

<%: Html.DisplayForModel("Table") %>

or

<%: Html.DisplayFor(m => m.SomeList, "Table") %>

Download the sample

As I typically do, I’ve written up a sample project you can try out in case you run into problems getting this to work. Note this sample was built for Visual Studio 2010 targetting ASP.NET 4. If you are running ASP.NET MVC 2 on Visual Studio 2008 SP1, just copy the Table.ascx into your own project but replace the Html encoding code nuggets <%: … %> to <%= Html.Encode(…) %>.

Here’s the link to the sample.

asp.net mvc, asp.net, code comments edit

Like the well disciplined secure developer that you are, when you built your ASP.NET MVC 1.0 application, you remembered to call Html.Encode every time you output a value that came from user input. Didn’t you?

Well, in ASP.NET MVC 2 running on ASP.NET 4, those calls can be replaced with the new HTML encoding syntax (aka code nugget). I’ve written a three part series on the topic.

But dang, going through all your source files cleaning up these calls is a pretty big pain. Don’t worry, I have your back. Just bring up the Find an Replace dialog (CTRL + SHIFT + H) and expand the Find options section and check the checkbox labeled Use and make sure Regular expressionsis selected.

Then enter the following in the Find what textbox.

\<\%:b*=:b*Html.Encode\({[^%]*}\):b*\%\>

And enter the following in the Replace with textbox.

<%: \1 %>

Here’s a screenshot of what the dialog should look like (though yours won’t have the red box :P).

find-and-replaceNote that this regular expression I’m giving you is not foolproof. There are some very rare edge cases where it might not work, but for the vast majority of cases, it should work fine. At least, it works on my machine!

works-on-my-machine

Now that I’m finally done with updates to Professional ASP.NET MVC 2, I hope to get back to my regular blogging schedule. This will be only my third blog post this month, a new record low! And I love to blog! It’s been a busy past few months.

asp.net, asp.net mvc, code comments edit

One annoyance that some developers have run into with ASP.NET MVC is that certain reserved filenames are not allowed in URLs. Often, this is manifested as a Bad Request error or a File Not Found (404) error.

The specifics of this restriction are accounted for in an interesting blog post entitled Zombie Operating Systems and ASP.NET MVC. This actually wasn’t a restriction on ASP.NET MVC but was built into the core of ASP.NET itself.

Fortunately, ASP.NET 4 fixes this issue with a new setting. In web.config, simply add <httpRuntime relaxedUrlToFileSystemMapping="true"/> to the system.web node. Here’s a snippet from my web.config.

<configuration>
  <system.web>
    <httpRuntime relaxedUrlToFileSystemMapping="true"/>

    <!-- ... your other settings ... -->
  </system.web>
</configuration>

Here is a screenshot of it working on my machine.

con-in-my-url

Now you are free to use COM1-9, LPT1-9, AUX, PRT, NUL, CON in your URLs. I know you were dying to do so. :)

What about web.config?

So the question comes up from time to time, “what if I want to have web.config in my URL?” Why would you want that? Well if you are StackOverflow.com, this makes sense because of the tagging system which places a tag (such as the “web.config” tag, into the URL. I’m not sure why anyone else would want it. ;)

The answer is yes, it works.

web.config-in-my-url

Please note, that you still can’t request /web.config because that would try to request web.config in the root of your web application and ASP.NET won’t allow that for good reason!

In fact, any request for a *.config file that doesn’t match a route will fail.

While I think the vast majority of developers really won’t encounter this issue, it’s a really improvement included in ASP.NET 4 for those that do care.

Keep in mind that this isn’t restricted to just these special names. For example, a URL segment ending with a dot such as the following URL http://example.com/version/1.0./something will not work unless you set the this web.config value.