February 2010 Blog Posts

Austin Texas The Techie Town

If there’s one impression that Austin left on me, besides the one that Rudy’s “extra moist” barbecue left on my gut, is that it’s a developer friendly town.

This past week I spent three days in Austin meeting with all sorts of developers and had many great conversations about technology. I met with companies and people with a passion for technology that couldn’t be suppressed.

Photo from http://www.treehugger.com/

Meeting with Dell

The reason I was in town was to give a couple of presentations at a mini-conference for Dell employees. On my first day in Austin, the day before the conference, I met with a team working on the next generation of Dell.com. The site is undergoing a large scale rearchitecture based heavily on ASP.NET MVC 2.

I fielded some questions on ASP.NET MVC and its future and was given a presentation on their new architecture. It was clear that they spent a lot of time with ASP.NET MVC as I even received an obscure question asking why Routing uses the ReaderWriterLock rather than ReaderWriterLockSlim? (The answer, in case you’re interested in that sort of trivia, is that ReaderWriterLockSlim didn’t work in medium trust in ASP.NET 3.5 SP1, but that’s been fixed in ASP.NET 4 and Routing now uses that).

I should mention that Dell is hiring in a big way. Many of these positions will involve a lot of ASP.NET MVC development.

We’re looking for senior level folks that have extensive e-commerce experience, are experts in Microsoft technologies (MVC knowledge a big plus), and have worked on some very large sites.  We’re looking for architects, dev leads, business analysts and project managers.  We have positions open in Round Rock, Tx (just north of Austin) as well as Bangalore, India.  Visit www.dell.com and click on Careers at the bottom of the page.

Austin .NET User group

After meeting with Dell, I was whisked over to the Austin .NET User Group meeting (ADNUG) where I gave a presentation on what’s new in ASP.NET MVC 2. The room was packed and the attendees were engaged with the talk. They had to be as my demos were failing left and right and I needed the help from the audience to catch my mistakes several times. Thank you ADNUG!

Afterwards I went with several user group attendees and was treated to Rudy’s Country Store and Bar-B-Q which is a gas station, convenience store, and Bar-B-Q shack. I would soon learn that Austin is full of these multi-function restaurants. I ordered the “Extra Moist” and some cream corn which was oh so delicious!

Back at Dell

After Rudy’s I spent the evening working on digestion and my demos. The next morning I spent the day at a small conference center presenting two talks to Dell employees, the intro talk I mentioned earlier and an ASP.NET MVC 2 Tips and Tricks talk.

This time, both talks went much more smoothly and I now feel much more prepared for the upcoming Mix 10.

After my talks at Dell, Jonathan Carter and I headed over to the WhipIn to meet up with the quiet and always subdued Scott Bellware. The WhipIn is a convenience store, bar, and Indian food restaurant with a slogan of “Namaste Y’all!”" Remember that thing I said earlier about multi-function restaurants?

Visiting Headspring

My last day in Austin was spent visiting two companies full of very talented software developers doing extensive work with ASP.NET and ASP.NET MVC.

I spent the morning at Headspring which employs many well known members of the .NET community as they’re involved in blogging, C4MVC, MvcContrib, etc. Jeffrey Palermo, Eric Hexter, Jimmy Bogard, Matt Hinze, amongst others (sorry, I don’t know your URLs).

One of the first things I noticed when walking into their office was a big screen TV displaying the statuses of several different builds from their Continuous Integration (CI) server. I watched as a Watin run provided a “ghost in the machine” demonstration of their automated functional test suite.

They walked me through their current project showing how they’re using and customizing ASP.NET MVC and we discussed potential improvements to ASP.NET MVC. One thing they’ve done as they’ve gained experience building ASP.NET MVC applications is to embed many of the lessons they’ve learned into the open source CodeCampServer project.

It may be overkill for what it is, a code camp management website, but the point of the site is to demonstrate practices they use on much larger projects.

Visiting Dovetail

After meeting with Headspring, I headed over to meet the DoveTail guys for lunch. Unfortunately, we didn’t go to Torchy’s since we were short on time and didn’t want to wait. Not only that, I had a sangria margarita for lunch and was carded. Those Austin-ites are sticklers for checking IDs.

We spent lunch discussing a wide range of topics on the .NET community, technology, etc. After lunch we headed over to their office where once again I saw a monitor with the status of their continuous integration server displayed on a monitor. Seems all these Austin developers see the value in continuous integration.

We settled in and Jeremy Miller, Chad Myers, Joshua Flanagan, et all walked me through what they’ve done with FubuMVC. I really liked several of the ideas they’ve put in their framework, some of which may show up in ASP.NET MVC in the future as is typical of technical cross-pollination.

Heading Home

After the meeting at Dovetail, I took a cab to the Austin airport to catch a flight home. Looking back, I wished I had been able to spend more time in Austin. Known as the live music capital of the world, I didn’t get a chance to hit the heart of the city.

Even so, I really enjoyed my visit there. The weather was nice and the local tech community seemed to be quite involved and vibrant. It’s definitely a place I want to visit again.

Manipulating Action Method Parameters

During the MVP summit, an attendee asked me for some help with a common scenario common among those building content management systems. He wanted his site to use human friendly URLs.

  http://example.com/pages/a-page-about-nothing/

instead of

  http://example.com/pages/123/

Notice how the first URL is descriptive whereas the second is not. The first URL contains a URL “slug” while the second one contains the ID for the content, typically associated with the ID in the database.

This is easy enough to set up with routing, but there’s a slight twist. He still wanted the action method which would respond to the first URL to have the integer integer ID as the parameter, not the slug. Let’s look at one possible approach to solving this.

Here’s an example of what the route might look like:

routes.MapRoute(
  "Slug", // Route name
  "pages/{slug}", // URL with parameters
  new { controller = "Home", action = "Content" } // Parameter defaults
);

Notice that the route URL contains one parameter for “slug” and no “id” parameter whatsoever. Here’s an example of the controller action that route should map to.

public ActionResult Content(int id)
{
  // Note the argument is an id, not slug
  return View();
}

Note that the action method does not accept a parameter named “slug” but instead expects an integer “id” parameter.

Fortunately, there’s an easy way to do this. Action filters, classes which derive from ActionFilterAttribute, allow hooking into the point in time after the parameters of action method have been bound, but just before the action method has been invoked. This gives us a fine opportunity to muck around with the parameters.

The following is an example of an action filter which converts a slug to an ID (you can imagine a real one would probably look it up in the database, not in a static dictionary like the sample does).

public class SlugToIdAttribute : ActionFilterAttribute
{
  static IDictionary<string, int> Slugs = new Dictionary<string, int>
  {
    {"this-is-a-slug", 100}, 
    {"another-slug", 101}, 
    {"and-another", 102}
  };

  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
    var slug = filterContext.RouteData.Values["slug"] as string;
    if(slug != null)
    {
      int id;
      Slugs.TryGetValue(slug, out id);
      filterContext.ActionParameters["id"] = id;
    }
    base.OnActionExecuting(filterContext);
  }
}

The filter overrides the OnActionExecuting method which is called just before the action method is called. The filter than grabs the slug from the route data, and looks up the corresponding id. Now all we need to do is make sure the id is passed into the action method.

Fortunately the filter context passed into this method allows us to peek into the parameters that will get passed into the action method via the ActionParameters property. Not only that, it allows us to change them!

In this case, I’m grabbing the slug from the route data, and looking up the associated id, and adding a parameter named “id” to the action parameters with the correct id value.

All I need to do now is apply this filter to the action method and when the action method is called, this id will be passed into the method.

This works whether the argument to the action method is a simple primitive type as in this example or whether it’s a complex type. I’ve included a sample project that demonstrates changing parameters to action methods via an action filter.

ASP.NET MVC 2 Optional URL Parameters

If you have a model object with a property named Id, you may have run into an issue where your model state is invalid when binding to that model even though you don’t have an “Id” field in your form.

The following scenario should clear up what I mean. Suppose you have the following simple model with two properties.

public class Product {
    public int Id { get; set; }
    public string Name { get; set; }
}

And you are creating a view to create a new Product. In such a view, you obviously don’t want the user to specify the Id.

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

  <fieldset>
    <legend>Fields</legend>
        
        
    <div class="editor-label">
      <%= Html.LabelFor(model => model.Name) %>
    </div>
    <div class="editor-field">
      <%= Html.TextBoxFor(model => model.Name) %>
      <%= Html.ValidationMessageFor(model => model.Name) %>
    </div>
       
    <p>
      <input type="submit" value="Create" />
    </p>
  </fieldset>

<% } %>

However, when you post it to an action method like so:

[HttpPost]
public ActionResult Index(Product p)
{
    if (!ModelState.IsValid) {
        throw new InvalidOperationException("Modelstate not valid");
    }
    return View();
}

You’ll find that the model state is not valid. What gives!?

Well the issue here is that the Id property of Product is being set to an empty string. Why is that happening when there is no “Id” field in your form? The answer to that, my friend, is routing.

When you crack open a freshly created ASP.NET MVC 1.0 application, you’ll notice the following default route defined.

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = "" }
);

To refresh your memory, that’s a route with three URL parameters (controller, action, id), each with a default value ("home", "index", "").

What this means is if you post a form to the URL /Home/Index, without specifying an “ID” in the URL, you’ll still have an empty string route value for the key “id”. And as it turns out, we use route values to bind to action method parameters.

In the scenario above, it just so happens that your model object happens to have a property with the same name, “Id”, as that route value, so the model binder attempts to set the value of the Id property to empty string, and since Id is a non-nullable int, we get a type conversion error.

This wouldn’t be so bad if “Id” wasn’t such a common name for properties. ;)

In ASP.NET MVC 2 RC 2, we added an MVC specific means to work around this issue via the new UrlParameter.Optional value. If you set the default value for a URL parameter to this special value, MVC makes sure to remove that key from the route value dictionary so that it doesn’t exist.

Thus the fix to the above scenario is to change the default route to:

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

With this in place, if there’s no ID in the URL, there won’t be a value for ID in the route values and thus we’ll never try to set a property named “Id” unless you have a form field named “Id”.

Note that this should be the default in the project templates for ASP.NET MVC 2 RTM.

Installing ASP.NET MVC 2 RC 2 on Visual Studio 2010 RC

As many of you have probably heard, the release candidate for Visual Studio 2010 was recently released containing immense performance improvements and tons of bug fixes.

Another thing that release contains is the release candidate for ASP.NET MVC 2. However, that release is not the latest release of ASP.NET MVC 2 as we recently released a second release candidate for ASP.NET MVC 2 in response to customer feedback.

I apologize for the confusion this may have caused, but we really felt it was important to have another release candidate for ASP.NET MVC to help verify that we were responding to feedback in the correct manner.

If you wish to have Visual Studio 2010 RC and ASP.NET MVC 2 RC 2 installed at the same time, it’s not a problem.

If you installed ASP.NET MVC 2 RC 2 Before installing VS 2010 RC

Believe it or not, you’re all set if you install them in this order.

When installing VS 2010 RC, the installation will detect that a newer version of the ASP.NET MVC runtime (aka the System.Web.Mvc assembly) is already installed and will not overwrite it with the older version included with VS 2010 RC.

Keep in mind that the project templates for VS 2010 will still be the slightly older ASP.NET MVC 2 RC project templates and not the RC 2 templates. Fortunately those templates haven’t changed too much between release candidates.

In this configuration, when you create a project using VS 2010 RC, even though the templates may be slightly older, the project will reference the newer System.Web.Mvc assembly.

If you are installing ASP.NET MVC 2 RC 2 After installing VS 2010 RC

In this case, there’s a tiny bit of work to do. The installer for ASP.NET MVC 2 RC 2 will block if an older version of the ASP.NET MVC 2 runtime is installed.

To remedy the situation, all you need to do is uninstall the ASP.NET MVC 2 runtime. In Add/Remove Programs dialog (also known as the Program and features dialog), this would be the entry named “Microsoft ASP.NET MVC 2”.

If you have an older version of MVC tooling/project templates for Visual Studio 2008 installed (named “Microsoft ASP.NET MVC 2 – Visual Studio 2008 Tools”), you’ll also need to uninstall that, but do not uninstall the MVC tooling for VS 2010.

add-remove-dialog 

At this point, you should only have Microsoft ASP.NET MVC 2 – Visual Studio Tools for VS 2010 installed. You may now run the installer for ASP.NET MVC 2 RC 2, which will put the runtime on your machine as well as tooling/project templates for VS 2008.

Hopefully this clears up some of the confusion and gets you going with VS 2010 RC and ASP.NET MVC 2 RC 2.

Headed To Austin and Speaking at the .NET User’s Group

UPDATE: We moved the date to February 24th.

The stars at night, are big and bright – clap clap clap clap – deep in the heart of Texas!

Hold onto your ten gallon hats, I’m visiting Texas for the first time! I’m very excited to visit the second largest state in the union. ;)

austin The purpose of my trip is to meet with some developers at Dell doing interesting things and to give a talk there as well.

But since I’ve heard such good things about the vibrant tech community in Austin, I am trying to make the most of my short trip. On Wednesday, February 24, I’ll be speaking at Austin .NET User Group meeting at 7:00 PM CST at the Microsoft offices in Austin. So be sure to come by and say hello.

We moved it to the 24th so if you were planning on attending Martin Fowler’s talk on February 25th, you can see both! Unfortunately for me, I was hoping to see Martin speak, but I saw that they’ve closed registration.

I’m also going to visit my good friends at Headspring as well as Dovetail Software to jabber about technology and see what cool things they’re doing with ASP.NET and ASP.NET MVC.

And of course, a trip to Austin wouldn’t be complete without a night out on the town with Bellware. I expect chaos. ;)

ASP.NET MVC 2 RC 2 Released

UPDATE: This blog post is out-of date. We released the RTM of ASP.NET MVC 2 in March 2010. Read about it here.

Today I’m pleased to announce the availability of Release Candidate 2 for ASP.NET MVC 2.

thumbs-upAfter receiving feedback from our last release candidate back in December, we decided it would be prudent to have one more release candidate that incorporated the feedback. You can read the release notes for everything that changed, there’s not a whole lot.

The biggest change in this release was described by Brad Wilson in his blog post on Input Validation vs. Model Validation in ASP.NET MVC. Also included in this release are an assortment of bug fixes and performance improvements.

The window to provide feedback on this release is going to be very short as we are closing in on the RTM. If you want to provide input into this release, please do take the bits for a spin as soon as possible. I’m pretty excited about this release as I can see the end of the tunnel fast approaching. :)

At this point, we’ll only be taking recall class bugs for ASP.NET MVC 2. All other bug reports will be filed against ASP.NET MVC 3. Sometime in the near future, I’ll start sharing some of our planning around that. How exciting!

Oh, and if you missed the link to the Download Details page at the beginning of this post, here it is again.

We also posted the source code and futures assembly on our Codeplex Site.

Can You Really Measure Customer Satisfaction?

One question that came up recently during my mid-year review is how am I measuring customer satisfaction with the products that I work on? For example, how can I measurably demonstrate that customers are happy with the work we are doing on ASP.NET MVC and that my team is responding to customer feedback?

Umm, I can’t?

At least not right now in a measurable manner. I don’t have any such metric and I’m not sure how reliable any metric I might come up with will be.

rulerBut perhaps that’s simply due to a lack of imagination on my part.

In the past, we’ve tried various unscientific online twitter polls. One thing we did was ask the world for a list of ASP.NET pain points and compile them into one big list. Then at the end of the product cycle, we could show that we were able to address 10% of those pain points.

Personally, I feel that’s a bit contrived, but if it satisfies the muckety mucks, it works for me. ;)

Well actually, I’m not satisfied with that. At least not until I’ve tried to come up with something better. So I started thinking about what are ways to measure this and apart from simply using SurveyMonkey, I’ve sort of hit a wall.

This is where I ask you the question. If you were in my shoes what would you do? How have you quantitatively measured your effectiveness in responding to customer input? I’d love to hear your ideas.

UPDATE 2/4 1:06 AM By the way, I didn’t mean to give the impression that this is the only metric I need to collect. This is just the one I need help with. I think the number of downloads, installations, and clients is a much more important metric. However, some of those numbers are hard to collect with any accuracy. That’s why I think some of these other metrics might be useful as corroborating evidence. At least that’s my theory.