Austin and Kaizenconf Part 2

Using and abusing ASP.NET MVC for fun and profit

Being a huge fan of ASP.NET MVC, I couldn't miss the opportunity to see guys that are much smarter than I am show off how they use the MVC framework. Jeremy and Chad showed real code of how they had been using the ASP.NET MVC framework in their projects.

Because this is a brand new framework, I have these moments when I'm using it that it doesn't feel quite right. I feel that the way I'm coding something isn't the best way to do it, but I don't know how to get around it. While sitting in the session I had a lot of aha-moments, I saw how other people tackled problems that I couldn't wrap my head around until now.

These are some key points that from now on I will try to keep in mind while using the ASP.NET MVC framework:

  • Keep your views light, your controllers medium and your model heavy
  • HttpContext is your enemy, controllers should not come in direct contact with the HttpContext even now it's mockable
  • Get rid of magic strings (for example hashtable examples like ViewData)
  • Thunderome principle
  • No if's or foreach's in the view, use extension methods, htmlhelpers and partial views to get rid of logic in your view

Another thing I couldn't wrap my head around before seeing this session was unit testing javascript with QUnit. I did write some tests with it but again bumped into some road blocks. It was great to see that other people used it with success. I'll probably be writing a blog post about this in the future, as I'm planning on taking the quality of my javascript code to the next level.

Last but not least was a demo that Jeremy gave of StoryTeller, it was a short demo but it looked very promising. I highly recommend viewing the session, you can find the video's at the KaizenConf wiki.

Presentation Patterns

This time Jeremy paired up with Glenn Block to tell us more about presentation patterns. They talked about several presentation patterns including passive view, supervising controller and view-viewmodel-model. The thing I realized is that I'm not using presentation patterns enough in my day to day job and that I should start using them where I can as soon as possible.

Open space

After the fantastic sessions it was time to kick off the open space. This was my first open space and I didn't really know what to expect. Doc List coordinated it all and it was a great learning experience. We started with a fishbowl, after which everyone participating could propose subjects. After that everyone voted and the topics that he or she was interested in. The schedule was formed.

An open space leans on four principles:

  • Whoever comes is the right people
  • Whatever happens is the only thing that could have
  • Whenever it starts is the right time
  • When it's over it's over

I followed a lot of sessions and have a lot of loose notes. I had a really good feeling with the concept of open space. The sessions are more debates and the participants discuss the things they want to talk about, not only what the speaker wants to show. Because almost everyone is participating you learn a lot from each other.

Conclusion

This was by far the best conference I've ever been to. I've learned so many things in such a short period of time. I would like to thank everyone who we met in Austin specially Conrad and Michael for letting us tag along and of course Scott for organizing the whole thing. If you are interested, there as a LOT of material produced you can find it on the KaizenConf wiki.


Creating a menu for your ASP.NET MVC website using HTML helpers

I've been working with ASP.NET MVC for a few months and it has been quite a ride. I'm working on a website where the menu is loaded from the database. It should be rendered as an unsorted list and a CSS class should be added to the active item. Here is an example of the menu:

<ul id="navigation">

    <li class="active"><a href="about-us.aspx">About us</a></li>

    <li><a href="location.aspx">Location</a></li>

    <li><a href="what-can-we-do-for-you.aspx">What can we do for you?</a></li>

    <li><a href="works-on-my-machine.aspx">Works on my machine</a></li>

</ul>

This is certainly no rocket science, a normal website navigation build with XHTML and CSS. Because ASP.NET MVC has no things as viewstate, server controls or postbacks we need another approach then what we're used to. In ASP.NET Web forms the unsorted list would probably be a server control which we then would manipulate in the code behind. But we're not using ASP.NET Web forms, we're using ASP.NET MVC and that's a good thing!

The first solution I found was adding a property to my Navigation model class called Active. So the Navigation class looked like this:

public class Navigation

{

    public virtual Int32 Id

    {

        get; set;

    }

 

    public virtual String Label

    {

        get; set;

    }

   

    public virtual String Link

    {

        get; set;

    }

 

    public virtual Boolean Active

    {

        get; set;

    }

}

Notice that the Link property maps to the action we want to perform.

In the controller I would first fetch the navigation items from the database and copy them to the ViewData property, then iterate through the collection of navigation items and compared the action of the current page to the navigation items in the collection. If the actions matched then the active item was found and the property was set. There were a few moral problems I had with this approach. First it was quite some code to do something simple as setting the active item of a menu. Second, and this was the worst problem, you had to add logic to your view in order to output the correct HTML for the active item. In the view something like this had to be done:

<% foreach(var navigationItem in (ViewData["navigation"] as TwotoContent.Domain.Models.Navigation[]))

   {

        if(navigationItem.Active)

        {

            %><li class="active"><%

        }

        else

        {

            %><li><%

        }

%>   

            <a href="<%= navigationItem.Link + ".aspx" %>">

                <%= navigationItem.Label %>

            </a>

        </li>

<% }%>

Oh crap! This resulted in logic in the view which could not be tested, on top of that it polluted the view. I started searching Google for better solutions and found this thread. The last post is actually the most valuable one. Ben Scheirman, who has a most excellent blog by the way, posted the tip to use HTML helpers for this purpose. I had read about HTML helpers, but unfortunately none of the helper methods that existed actually did what I needed. So I decided to create my own. Drew Miller wrote a nice post about writing your own HTML helper.

Here are a few advantages about creating your own HTML helper:

  • Your view doesn't get cluttered
  • The code in the HTML helper is testable
  • Less code in your controller, this means less code to maintain which is always a good thing

So I created the following extension on the HTML helper class:

public static String NavigationItem(this HtmlHelper htmlHelper,

                                    String actionLink,

                                    String controller,

                                    String itemTitle)

{

    var htmlTemplate = htmlHelper.ActionLink(itemTitle, actionLink, controller) + "</li>";

    var action = htmlHelper.ViewContext.RouteData.Values["action"];

 

    if(String.Compare(actionLink, action.ToString(), true, CultureInfo.InvariantCulture) == 0)

    {

        htmlTemplate = "<li class=\"active\">" + htmlTemplate;

    }

    else

    {

        htmlTemplate = "<li>" + htmlTemplate;

    }

 

    return String.Format(htmlTemplate, actionLink, itemTitle);

}

 

As you can see I do use one helper method, the ActionLink method, in order to create a link for the given action for the given controller. The advantage of using ActionLink is that it takes the defined routes into account so you don't have to worry about that. Then we compare the given action to the current action if those two are equal we generate a list item with the correct class, otherwise we just generate a list item. Now we can write something like this in our view:

<% foreach(var navigationItem in (ViewData["navigation"] as TwotoContent.Domain.Models.Navigation[]))

   {

       Html.NavigationItem(navigationItem.Link, "mycontroller", navigationItem.Label);

   }

%>   

This will generate the menu just as we want it to be. I'm sure this solution still has drawbacks but I hope you agree this is a big improvement compared to the first solution. If you have any suggestions to improvement, questions or remarks I'll be glad to listen to them.