Matt Lee

Software Engineer at Red Gate Software, Maker of funky apps.

  • Why ASP.NET MVC is better - using 'Hello' as an example

    Posted Wednesday, September 30, 2009 4:12 PM | 5 Comments

    In this second post about Hello (the first can be found here), I'm going to use one of the more complex portions of the app, the event front page, to illustrate some of the various parts of MVC which make writing web apps more intuitive.

    The web app of the Hello project was written in ASP.NET MVC, which is Microsoft's latest addition to the ASP.NET framework. It uses the Model, View, Controller design pattern and is influenced heavily by frameworks like Ruby on Rails.

    Fig. 1 - The event front page of Hello displays the seating for the event; each chair is represented by a square and if there is a user in the chair we display their twitter avatar.

    To produce the event page, there are several stages that the app goes through - for an awesome outline of the ASP.NET MVC Request-Handling Pipeline, see this poster. Firstly the URL is routed through to the correct controller. We decided that we wanted the front page for an event to live under a really simple URL: /eventslug, where eventslug would be a short string to uniquely identify the event. For example, for the Future of Web Apps event we might have the URL /fowa. From the event page you can search the users at the event, and we decided the intuitive URL for the search should be /eventslug/search. You configure the URLs in the Global.asax.cs file as follows:

    routes.MapRoute(null,
    "{eventslug}/{action}",
    new { controller = "Event",, action = "Index", }, // Defaults
    new { eventslug = Settings.EventSlugRegex } // Contraints
    );

    From here the framework calls an action on your controller. If you’ve not started using MVC yet, a controller in an object that inherits from the abstract class System.Web.Mvc.Controller and an action is a public method of a controller. The signature for our action that will be called for /fowa is:

    public ActionResult Index(string eventslug)

    We call it Index because that’s the default action that we specified in the routing configuration. The framework will automagically map the value of the eventslug argument to the value that matches the {eventslug} portion of the URL; In the case of /fowa it will be the string "fowa"*.

    Then, in our action method, we grab the data relevant to the event with the requested event slug, and pass it to the view by calling View().

    var theEvent = _repo
    .Events
    .SingleOrDefault(e => e.Slug == eventslug);
    return View(theEvent);

    Calling the View method with theEvent as an argument means that in the view, the Model property of the ViewPage object will be the theEvent that was just retrieved from the repo. In MVC the view is an aspx page without a code behind class. The view is actually a ViewPage<T> object, which is a subclass of the old Page object that you’re familiar with from WebForms, where T is the type of the Model property. What this means is that in the view we get intellisense on our domain object:

    Fig. 2 - Intellisense in the view code on the statically typed Model property.

    In the view we also have complete control of our HTML, which was invaluable for this page as we had to get the layout just right in all the major browsers. So we just iterate over our rows of seats rendering the smiley.jpg image for an empty seat (sat == null) and when someone is in a seat we render their Twitter avatar.

    <table class="seatingPlan" cellpadding="0" cellspacing="0" border="0">
    <% var sats = (IList<Sat>)ViewData["Sats"]; %>
    <% foreach (var row in Model.Seats.GroupBy(s => s.Row)) { %>
    <tr>
    <% foreach (var seat in row) { %>
    <td>
    <% var sat = sats.SingleOrDefault(s => s.SeatID == seat.SeatID); %>
    <% if (sat == null) { %>
    <img src="<%= Url.Content("~/Content/images/presentation/smiley.jpg") %>" />
    <% } else { %>
    <img src="<%= sat.User.ImageURL %>" />
    <% } %>
    </td>
    <% } %>
    </tr>
    <% } %>
    </table>

    This is much more intuitive and clear than having to create a user control class which is then dynamically instantiated in the code behind and added as a child control of an ASP TableRow, which is then in turn added to an ASP Table, etc. Your code in front would of been basically one line...

    <asp:Table runat="server" ID="SeatsTable" />

    ... Totally hiding the complexity in the code behind, which would probably have been a mess of data access code and layout styling knotted together. Which is what you would have done in WebForms.

    So why is this better? There are probably two key differences between WebForms and MVC. Firstly, separation of concerns: MVC encourages you to separate out your domain model from your UI from your URL routing. WebForms actually makes that quite difficult; if anything, the code in front/behind paradigm encourages the reverse. Secondly, no unnecessary leaky abstractions: WebForms tries to hide from the developer the fact that he is working in a world of string manipulation over a stateless protocol. In the simple case this can work well, e.g. the classic click-the-button-to-make-the-label-say-hello example. But in the real world, the abstraction soon gets in the way, and you end up having to work really hard to achieve something quite simple. In MVC there is no abstraction to battle against, you have complete control of all parts of your web app. I’m going to put myself out there and say that MVC should be seen as a replacement to WebForms, as I don’t think there are any real world cases when MVC is not the right choice.

    * this isn't strictly true, the arguments of an action can be mapped from 1 of three places - the URL, query string paramenters, or form values.

  • ASP.NET MVC & Twitter Integration - getting inside 'Hello'

    Posted Thursday, September 03, 2009 4:39 PM | 1501 Comments

    I recently teamed up with Ryan Carson, Keir Whitaker and Mike Kus from Carsonified to write an application called 'Hello', with the catchy tagline "Turn to your neighbour and say...", geddit?! The motivation behind the project was to write something within a tight timescale that used a complete Microsoft stack, capped by ASP.NET MVC, and I thought that some of my experiences might be interesting to other people. This post will be the first in a series that will hopefully cover the techy side as well as the 'managerial' / logistical aspects. I'll give an initial overview of the project and its component parts, with some code thrown in to whet your appetite.

    Overview

    Hello helps you to meet interesting people at FOWA London. You can say where you're sitting, earn points, badges and post messages to the whole audience.

    As the description on Hello's front page says. The basic idea is that it is an app to encourage social interaction at events, namely FOWA London. Unusually, all input in to the app comes from Twitter, so the architecture looks something like this:

    The arrows show the flow of information - the arrow from the User to Twitter represents the flow of information from the user to Twitter by means of tweeting (unsurprisingly). To give you an example of how this works, if you wanted to join in with this Hello thing you could send a tweet that looked something like:

    @HelloApp hello !dev #csharp #aspnetmvc #jquery

    This would sign you up for Hello with a category of Developer, and then the hashtags that describe you. Hello gets really interesting on Conference Day when you're able to tweet messages saying where you're sitting, who you've met, tokens you've found or been given, and so on. And why would you want to do all these things? To win points of course - each action has an associated number of points. And why do you want points? Well because the more points you have then, clearly, the cooler you are. Not only do you look cool though, but you can then also tweet your own personal message and get it seen on the conference home page. A perfect opportunity to let people know you're hiring, or advertise your latest startup. Now that we know the users categories, hashtags and where they're sitting, you can then browse the seating chart and see who is sitting around you, what their interests are, and whether you have anything in common. You can also search the audience for specific names or skillsets (php, designer, CSS3, etc). Simple, but fun.

    But how does all this work?

    The Bot - Getting tweets from twitter

    There are a couple of APIs out there for accessing Twitter from .NET code; I went with TweetSharp, which has a fluent API; the code for grabbing all the mentions of a particular username looks like this:

    var tweets = FluentTwitter
        .CreateRequest()
        .AuthenticateAs(
            Settings.TwitterBotUsername,
            Settings.TwitterBotPassword)
        .Statuses()
        .Mentions()
        .Request()
        .AsStatuses();

    Pretty straight forward.

    Those tweets are then queued and processed, using the repo for storage...

    The Repo - LINQ to SQL

    We used LINQ to SQL for the backend, I love it for its simplicity and ease of use. We knew from the outset that we weren't going to have a hugely complex schema, so some of the weaknesses of LINQ to SQL wouldn't be a problem. After creating the database in SSMS, I switched over to Visual Studio and dragged the tables from the Server Explorer on to the Object Relational Designer. This generated all the domain objects for my application. The real highlight for me is that I don't have to mess around with SqlCommands or SqlDataReaders anymore. I love what you get, pretty much, for free, for example:

    var messages = _repo
        .Messages
        .Where(m => !m.Offensive
            && m.User.Points.Sum(p => p.Amount) > Settings.Thresholds.Silver)
        .OrderBy(m => (m.User.Created.Millisecond * randomOffset) % 1000)
        .Take(Settings.MaxMessages);

    Sweet, huh?!

    The Web App - Intro to ASP.NET MVC

    For the web portion of the project we used the latest iteration of Microsoft's web framework, ASP.NET MVC. For anyone keen to know more, there are lots of introductions to ASP.NET MVC out there on the web. To get up and running we used the Web Platform Installer, which makes the install process real easy. Mike, the designer working on the project, put together some awesome designs for the main pages of the site; the front page, search, and the conference day page. They looked something like this:

    I then translated these to view pages, and MVC makes this really simple as you don't have to fight against the HTML produced server controls. Although the responsibility of writing more HTML by hand can be a higher initial overhead, the long term gain of tight control over your markup is well worth it. Specifically, this is what goes in:

    <% foreach (var message in (IQueryable<Message>)ViewData["Messages"]) { %>
        <div class="message">
            <blockquote><p>"<%= message.Text %>"</p></blockquote>
            <p class="author">
    By @<a href="http://twitter.com/<%= message.Username %>">
    <%= message.Username %></a>
    </
    p> </div><!-- /.message --> <% } %>

    And the output...

    <div class="message">
        <blockquote><p>"Ben's message is cool!"</p></blockquote>
        <p class="author">
    By @<a href="http://twitter.com/benadderson">
    benadderson</a>
    </
    p> </div><!-- /.message --> <div class="message"> <blockquote><p>"Business is booming and we're hiring. Whoop whoop!"
    </
    p></blockquote> <p class="author">
    By @<a href="http://twitter.com/thatismatt">
    thatismatt</a>
    </
    p> </div><!-- /.message -->

    Lovely, clean HTML that exactly matches what I was given by Mike. Gone are the days when you have to convince your designer that he can't use a div with that class there because you're using an ASP GridPanel.

    The added flexibility in the View code does give you more power and, as we all know, "With great power comes great responsibility". But seriously, you do have to watch that you don't tie yourself in knots with too much code in your view.

    Wrap up

    I found the project really interesting, and working with ASP.NET MVC is such a joy coming from Web Forms, and has pacified my framework envy of such creations as Django and Rails. The Twitter integration was also challenging, and taught me a lot about writing applications with dependencies on external services. And the fact that the project was all written on such a tight schedule meant it had such a different feel to the line-of-business projects I'm normally on. I’ll pull out a bit more detail on a few of these topics in the next few posts, but leave a comment if there’s anything specific you’re interested in.



















<February 2010>
SuMoTuWeThFrSa
31123456
78910111213
14151617181920
21222324252627
28123456
78910111213
Finding Stuff in SQL Server Database DDL
 You'd have thought that nothing would be easier than using SQL Server Management Studio (SSMS) for... Read more...

Mission Critical: SQL Server 2008 Performance Tuning Task List
 In which Buck Woody imagines how the US military would have tackled DBA checklists for... Read more...

Simple Query tuning with STATISTICS IO and Execution plans
 A great deal can be gleaned from the use of the STATISTICS IO and the execution plan, when you are... Read more...

Switching rows and columns in SQL
 When they use SQL Server, one the commoner questions that Ms Access programmers ask is 'Where's the... Read more...

Writing Efficient SQL: Set-Based Speed Phreakery
 Phil Factor's SQL Speed Phreak challenge is an event where coders battle to produce the fastest code to... Read more...