Wed, 27 Oct 2010

Building a Mobile-Browser-Friendly List of PDC 2010 Sessions with Windows Azure and OData

I learned today that there’s an OData feed of all the PDC 2010 sessions. I couldn’t help but build a Windows Azure application that consumes that feed and provides a simple web page that works well on mobile browsers. You can use it at http://pdc10sessions.cloudapp.net.

I’m enjoying the ease of use of OData in .NET. OData is the protocol that Windows Azure tables uses, and I’m also starting to use that to expose data in other applications I write. To share the joy, I thought I’d share how I built this app.

All I did was add a service reference to http://odata.microsoftpdc.com/ODataSchedule.svc and write a simple controller method.  Here’s the controller method:


// cache for thirty seconds
[OutputCache(Duration=30000, VaryByParam="*")]
public ActionResult Index()
{
    var svc = new ScheduleModel(new Uri("http://odata.microsoftpdc.com/ODataSchedule.svc"));

    // prefetch presenters to join locally
    var presenters = svc.Speakers.ToDictionary(p => p.Id);

    // prefetch timeslots to join locally
    var timeslots = svc.TimeSlots.ToDictionary(t => t.Id);

    var sessions =
        from session in svc.Sessions.Expand("Presenters").ToList()
        where session.TimeSlotId != Guid.Empty // skip the recorded sessions
        let timeslot = timeslots[session.TimeSlotId]
        let presenter = session.Presenters.Count > 0 ? presenters[session.Presenters[0].Id] : null
        orderby timeslot.Start
        // tuple because I'm too lazy to make a class :)
        select Tuple.Create(session, presenter, timeslot.Start == DateTime.MaxValue
            ? "recorded session" : timeslot.Start.ToString());

    return View(sessions);
}

And here’s the ASP.NET MVC page:

<%@ Import Namespace="PDCSchedule_WebRole.ScheduleService" %>
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
    Inherits="System.Web.Mvc.ViewPage<IEnumerable<System.Tuple<Session, Speaker, string>>>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    PDC 2010 Session Schedule
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <% foreach (var tuple in Model) {
          var session = tuple.Item1;
          var speaker = tuple.Item2;
          var startTime = tuple.Item3; %>
          <div class="session">
            <h1 class="title">
                <%: session.FullTitle %>
                <%: speaker != null
                    ? string.Format(" ({0})", speaker.FullName)
                    : string.Empty %>
            </h1>
            <p class="location">
                <%: startTime %><%: !string.IsNullOrEmpty(session.Room)
                                    ? string.Format(" ({0})", session.Room)
                                    : string.Empty %>
            </p>
            <p class="description"><%: session.FullDescription %></p>
          </div>
    <% } %>
</asp:Content>

The only other important thing I did was add a meta tag to get mobile browsers to use the right viewport size:

<meta name="viewport" content="width:320" />

I’ll be using this at PDC this Thursday and Friday to find the sessions I’m interested in. If you’ll be attending PDC in person, I hope you find this useful too.