Last listened to Symphony No. 4 in G (1993 Digital Remaster): III. Ruhevoll by Paul Kletzki (on 6 Sep 2010, 05:25)

I use last.fm and let it's audioscrobbler services keep a track of whatever music I listen to. As you can see, just below the navigation bar on this website I use its API to display the last track I listened to.

Here's what it looks like when it's in action:

It's incredibly easy to add this onto your website too, if you're an ASP.NET developer. Here's how.

Create a new User Control in your website, and call it MostRecentTrack.ascx. In the codebehind file, copy and paste the following:

protected XElement MostRecentTrack { get; set; }

protected void Page_Load(object sender, EventArgs e)
{
    GetLatestTrack();

    if (MostRecentTrack == null)
        LatestTrackHolder.Visible = false;
}


private void GetLatestTrack()
{
    MostRecentTrack = Cache["MostRecentTrack"] as XElement;
    if (MostRecentTrack != null) return;

    string xmlLocation =
        string.Format("http://ws.audioscrobbler.com/1.0/user/{0}/recenttracks.xml",
                      LastFmUsername.Text);

    try
    {
        MostRecentTrack = XDocument.Load(xmlLocation).Descendants("track").First();
        Cache.Insert("MostRecentTrack",
                     MostRecentTrack,
                     null,
                     DateTime.MaxValue,
                     TimeSpan.FromMinutes(10));
    }
    catch
    {
        // Catch everything so that any failure doesn't bring the website down
        MostRecentTrack = null;
    }
}

In the HTML section of your control, put the following code:

<asp:PlaceHolder ID="LatestTrackHolder" runat="server">
    <p class="LatestTrack">
        Last listened to <%= (string) MostRecentTrack.Element("name") %>
        by <%= (string) MostRecentTrack.Element("artist") %>
        (on <%= (string) MostRecentTrack.Element("date") %>)
    </p>
    <asp:Literal ID="LastFmUsername" runat="server"
                 Visible="false"
                 Text="YOUR_USERNAME_HERE" />
</asp:PlaceHolder>

This code uses System.Linq and System.Xml.Linq so don't forget to add the relevant references. Also, don't forget to put your real last.fm username in the hidden Literal in your HTML code. When you've created your control, add it to your page like this:

<%@ Register Src="~/MyUserControls/MostRecentTrack.ascx"
    TagName="MostRecentTrack" TagPrefix="lastFm" %>

<lastFm:MostRecentTrack runat="server" />

I've got it below my navigation menu on my master page, so it shows up on every page.

ASP.NET Development Server problems

I got to work today and was unable to connect to any web sites using the built in ASP.NET Development Server.  In Internet Explorer I got the following message: "Internet Explorer cannot display the webpage" and in Firefox the message was "Failed to Connect" and "The connection was refused when attempting to contact localhost:3503".

This was strange, I had no problems yesterday, and no updates to .NET or Visual Studio had been installed on my machine overnight. Looking at windows update history, the only thing that had changed was an update to the Windows Defender definition file. Surely that can't be the problem, I thought. After a long time scratching my head, it appears that the problem was indeed Windows Defender and on further investigation I found this in my Windows Defender history:

Windows Defender History

So it appears that last night, Windows Defender removed this line from my hosts file (C:\Windows\System32\drivers\etc):

127.0.0.1    localhost

and either added or left behind the following line:

::1    localhost

Windows Defender has "defended" me from developing on my local machine, because localhost isnæt mapped correctly. To fix this problem, adding the first example (above) back into my hosts file and removing the second example fixed the problem.

I wonder how many other developers this affected?

Taking an ASP.NET website offline, the easy way

I've just come across Ryan Farley's post about taking an ASP.NET website offline, and it was something I didn't know about and I'm not sure many other people know about either. To take an entire ASP.NET website down, forget configuring IIS or anything like that - instead, simply upload a file named "app_offline.htm" into your webroot and you're done. All requests to any files in that application will be sent to the app_offline file, without you doing anything. How simple!

Before you use this approach, though, there are some situations where it's not as simple as uploading one file, such as:

  • If your ASP.NET site runs on a web farm across multiple servers.
  • If your ASP.NET site has another ASP.NET application in a virtual folder, for example.
  • If you foolishly add this file to your visual studio solution and accidentally release it when you're doing your next deployment!

When using an ASP.NET File Upload control (or the HTML equivalent) it's worth remembering that when you come to use the FileName property in your code, it annoyingly has different values depending on what browser you are using.

If you have one of these on your page...

<asp:FileUpload id="FileUpload1" runat="server" /> 

... or the HTML version...

<input id="FileUpload2" runat="server" type="file" />

... when you come to get the name of the user-selected file in your code (which for example was a file picture.jpg in C:\Pics\), you will get the following results depending on the users browser:

Control: FileUpload1 FileUpload1 FileUpload2 FileUpload2
Property: FileName PostedFile.FileName Value PostedFile.FileName
Firefox 2 picture.jpg picture.jpg picture.jpg picture.jpg
Firefox 3 picture.jpg picture.jpg picture.jpg picture.jpg
IE7 picture.jpg C:\Pics\picture.jpg C:\Pics\picture.jpg C:\Pics\picture.jpg
Opera 9 picture.jpg picture.jpg picture.jpg picture.jpg
Safari 3 picture.jpg picture.jpg picture.jpg picture.jpg

As you can see, it is Internet Explorer that is the odd one out. What this means is that you can't rely on using the FileName property without first checking the value and trimming out the unwanted file path. For example, to get picture.jpg no matter what browser is used, you'll have to do something like this:

string file = FileUpload2.PostedFile.FileName;
int slash = file.LastIndexOf("\\");
if (slash > 0) file = file.Substring(slash, file.Length - 1);

Don't let this catch you out.