Windows Live Quick Apps – Contoso Bicycle Club

The Contoso Bicycle Club is a demonstration website put together to show off a number of Windows Live technologies and how easy it is to integrate these technologies into your own websites. The source code for both this web site and a second web site entitled Contoso University are available for download from CodePlex.

One note before we proceed any further. Both of these websites are written to run with Visual Studio Orcas (Beta 2 and above). Both applications also use Asp.Net Ajax and the Contoso Bicycle Club also requires the Asp.Net Ajax Toolkit. Both Asp.Net Ajax, the Toolkit and also Asp.Net Ajax Futures are freely downloadable from here.

So lets start at the beginning with a quick run through of the home page. Once you have everything setup and run CBC website, you will be greeted with a rather nice looking home page :

bikeclubmain_thumb Developer

The default.aspx page (above) is coded in a nice way, splitting the page into a number of manageable user controls which are registered at the top of the page (we’ll get into these later). A quick look through the code and you’ll notice that the default.aspx page also takes advantage of .Net 2.0 Themes. The default theme (named default) is coded into the web.config file :-

<pages theme=”Default” enableViewState=”false”>

Next is the inclusion of the Asp.Net Ajax ScriptManager tag and within there a number of scripts are registered with the page. Most of these scripts are included in the application however there are two noticeable scripts that have external references (therefore in order to run this website locally you still need an internet connection). One of the scripts references the Virtual Earth MapControl and the other is a Silverlight helper file.

Below the ScriptManager tag the site defines a couple of areas that will be used for Ride information (using a user control) and Events (again using a user control).

Next the default.aspx defines a number of menu tabs (as you can see along the top of the page). These are coded in a “W3C friendly layout” as opposed to using tables to position everything.

The main area of the page is mostly taken up with an area reserved for the map control (initially hidden).

An embedded iFrame tag sets up a slideshow and finally a few more areas are defined for directions, a text only panel, the footer you see along the bottom of the page giving you links to the source and a live site website where this demonstration site is actually being hosted, and an area reserved for the Main page.

The code behind for the default page simply returns the images for use in the slideshow iFrame.

So now that we have a quick outline of the home page, lets dig in a little further, see what the user controls do and see exactly how this page is put together. We’ll start out easy.

Events Control

eventscontrol_thumb Developer

This control which displays on the bottom left of the page takes an RSS feed gathered from a Windows Live Spaces site, formats it and displays it. So how is this done?

Every Windows Live Spaces site exposes various RSS feeds by default. You have a main feed that details all the posts that you have made. You also get individual feeds for each category that you file a post under. Some categories are predefined for you but you have complete freedom in adding your own categories. The easiest way of doing this is to simply fire up Live Writer. At the bottom of Live Writer there is a categories drop down, here you add a new category when you post a blog and this will be created in Spaces for you. You also need to go to your spaces site, login and select “Space settings” from the options menu and make sure that you have syndication turned on.

To get the URL that you require is very easy. For your main “everything” RSS feed, it’s simply the URL of your spaces site followed by “/feed.rss”. If you want a feed for a specific category then again it’s simple, take the URL to your spaces site and add “/category/” followed by the category that you wish followed by “/feed.rss”.

For example, one of my spaces sites resides at http://msnwindowslive.spaces.live.com.

To get the feed for the whole site would simply be http://msnwindowslive.spaces.live.com/feed.rss. To get the feed for a category I’ve setup called Books it would simply be http://msnwindowslive.spaces.live.com/category/books/feed.rss.

Now that you know how the spaces feeds are constructed, take a look in the Web.config file of the CBC web site and under the AppSettings section you will notice that this application actually uses three separate RSS feeds from Windows Live Spaces :-

<appSettings>

<!– Content Feeds – RIDES –>

<add key=”LatestRidesFeed” value=”http://contosobicycleclub.spaces.live.com/category/rides/feed.rss”/>

<!– Content Feeds – FORUM –>

<add key=”ForumFeed” value=”http://contosobicycleclub.spaces.live.com/category/forum/feed.rss”/>

<!– Content Feeds – EVENTS –>

<add key=”EventsFeed” value=”http://contosobicycleclub.spaces.live.com/category/events/feed.rss”/>

….

</appSettings>

The one that we’re currently interested in is the EventsFeed. As you can see this is pointing to http://contosobicycleclub.spaces.live.com/category/events/feed.rss. You can right click and view source to take a look at the xml if you wish.

So back to the Events Control.

At the top of the control a JavaScript variable is initialized to 1. This is a counter that will be used in a JavaScript function to effectively give each blog its own item number (ID).

Next a XmlDataSource is defined. Nothing fancy here although a couple of things may appear to be unusual.

<asp:XmlDataSource ID=”eventsDataSource”

runat=”server”

EnableCaching=”false”

DataFile=”<%$ AppSettings:EventsFeed %>”

XPath=”/rss/channel/item”>

</asp:XmlDataSource>

The DataFile path uses a shortcut that was introduced in Asp.Net 2.0 to EventsFeed item found in the AppSettings section of the web.config file.

This is essentially equivalent to the following line of code :-

ConfigurationManager.AppSettings[“EventsFeed”]

The other is the Xpath setting. This is just a normal XPath path. You can think of it like a folder heirarchy. If you take a look at the actual RSS feed, you’ll see that “rss” is the top level element, under that there is a single channel tag that encapsulates the whole feel then there are a number of tags detailing such things as the title, a description, a link back to the actual article and so on. The one we’re interested is the item tag and all the tags under that item tag. There will be one item tag per blog post. Under each item you will find tags such as a link back to that specific blog post, the title of the blog, the date is was written, a permalink, any comments etc.

So in effect what we have done with the above XmlDataSource is to create a data feed for all blog posts found in the Contoso Windows Live Spaces site that have been filed under the category of Events.

Next we have a DataList control, which is just another repeater control. The DataList control takes in the XmlDataSource then defines how to display the data. It goes through each item (blog post) and applies a display template to it. In this example there are basically two different sections.

<div class=”title”>

<a href=”javascript:showDiv($(‘contentPanel’), 400);updatePage(‘<%# XPath(“title”) %>’,'<%= eventsDataSource.DataFile %>’, <%= n++%> ,'<%# HtmlProcessor.ExtractMapCid(XPath(“description”).ToString()) %>’,'<%# HtmlProcessor.ExtractPhotoAlbumFeed(XPath(“description”).ToString()) %>’)”>

<span class=”subTitle”><%# XPath(“title”) %></span>

</a>

</div>

The first output above may look complicated but it’s really not. First we’re defining a link. Within the link we’re first telling it to unhide the contentPanel that is defined in the default.aspx. The second parameter is simply the z-index. Here is the Javascript function that it calls :-

// Shows a DIV tag

function showDiv(div, zIndex) {

div.style.visibility = ‘visible’;

div.style.zIndex = zIndex;

// Work around for Bugzilla Bug 187435 for Firefox on Mac

if(div.id.toLowerCase() == “directionspanel” || div.id.toLowerCase() == “textpanel” || div.id.toLowerCase() == “mainpanel”)

{

div.style.overflow = “auto”;

}

}

Barring the Firefox workaround, as you can see, very straightforward.

Next we call the updatePage javascript function passing through some parameters. The first parameter is the Blog Title taken from the XmlDataSource, the next is the actual blog post itself, the third is the counter that was defined at the top of the page. Think of this as an ID number. The last two parameters for the javascript function call both use a class you will find in the Classes folder of the project, HtmlProcessor.

The first makes a call to ExtractMapCid, this returns an id for a virtual earth map collection that is taken from within the description of the blog post.

The second makes a call to ExtractPhotoAlbumFeed which returns a url to a Windows Live Spaces photo album RSS feed.

The Events Control however does not use maps or photographs therefore these last two parameters always return empty strings after the call the HtmlProcessor.

Embedded in the link is the actual text that will be displayed and for this we’re simply putting the title of the blog post within a <span> tag.

After all is said and done, this is the output for the first blog post from the Bicylcle club :-

<div class=”title”>

<a href=”javascript:showDiv($(‘contentPanel’), 400);updatePage(‘North End’,’http://contosobicycleclub.spaces.live.com/category/events/feed.rss’, 1 ,”,”)”>

<span class=”subTitle”>North End</span>

</a>

</div>

We show the contentPanel for events, display the title as a hyperlink with the link calling a javascript function to update the page passing through the title of the blog post, the whole blog post feed and an ID number.

The second part of the DataList calls the HtmlProcessor class once again :-

<div class=”description”>

<%# HtmlProcessor.FirstLine(XPath(“description”).ToString()) %>

</div>

This time we’re calling the function FirstLine and passing in the contents of the description Xml tag taken from the XmlDataSource for that blog post :-

public static string FirstLine(string html)

{

Regex regex = new Regex(“(.*?)\.”);

Match match = regex.Match(html);

if (match.Groups.Count > 1)

return match.Groups[1].Value;

else return “”;

}

This is a fairly simple function that parses through the passed in html looking for the first full stop at the end of a sentence and extracts that sentence. The returned sentence is what will be displayed on screen.

That’s all there is to this user control, simple. So how do you incorporate this into your own websites without all the fancy javascript etc. from the Bicycle application?

simpleapp_thumb Developer

Fire up Visual Studio and create a new Web Site. For this example we just need to create a standard web site (don’t need Ajax). For this demo we’re simply going to put a textbox on the page to enter the location of a spaces feed, a button control so that we can take the value entered and bind it to our data source control, and a repeater to display the contents.

We won’t bother with CSS to make things look nice as this example is just here to show how easy it is to display a Windows Live Spaces RSS feed in your own site, you can add a stylesheet to this code if you so wish.

So after the project has been created, we need to create our controls on the default.aspx page as described above. Here is the simple code for our default.aspx page :-

<%@ Page Language=”C#” AutoEventWireup=”true” CodeFile=”Default.aspx.cs” Inherits=”_Default” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >

<head runat=”server”>

<title>Untitled Page</title>

</head>

<body>

<form id=”form1″ runat=”server”>

<div>

<asp:TextBox ID=”Feed” runat=”server” Columns=”60″ />

<br />

<asp:Button ID=”btnSubmit” runat=”server” OnClick=”btnSubmit_Click” Text=”Get Feed” />

<br />

<br />

<asp:XmlDataSource ID=”source” runat=”server” XPath=”/rss/channel/item” DataFile=”http://msnwindowslive.spaces.live.com/feed.rss” />

<asp:Repeater DataSourceID=”source” ID=”DisplayFeed” runat=”server”>

<ItemTemplate>

<div>

<a href='<%# XPath(“link”) %>’>

<%# XPath(“title”) %>

</a>

<hr />

<%# XPath(“description”) %>

<br />

<br />

</div>

</ItemTemplate>

</asp:Repeater>

</div>

</form>

</body>

</html>

All very simple. The code behind is even simpler :-

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

    {

    }

public static string GetFirstXCharacters(string description, int x)

  {

return description.Substring(0, x);

  }

protected void btnSubmit_Click(object sender, EventArgs e)

  {

    source.DataFile = Feed.Text;

  }

}

For the above example, the only method that we require is the btnSubmit_Click event handler. In this we simply set the datafile (RSS feed) of our DataSource control to the value that has been entered into the textbox, and that’s it. Of course in a real web application you would parse the value entered to make sure that it was correct and add error handling.

The other method in this web config file simply returns the first x characters of each blog description. In order to hook the code up to use this method you simply replace the line in the default.aspx page that reads :-

<%# XPath(“description”) %>

With this :-

<%# GetFirstXCharacters(XPath(“description”).ToString(), 500) %>

Of course you can replace this with any method call that you wish, for example to parse the description field to extract certain values.

In the next part of this tutorial we will move onto the Latest Rides control.