Parsing Yahoo! Music's Artist Web Services with C# and LINQ to XML - Search for artists

Similar to my post on parsing Last.fm's artist.getSimilar, I've been working with Yahoo! Music's Web services today.

Unfortunately, Yahoo!'s services aren't quite as friendly as those made available by Last.fm.

So that I remember, and others don't have to tackle this as well, here's the class I've created. (Download JamesRSkemp.WebServices.YahooMusic.cs.)

/*
Created by James Skemp - http://jamesrskemp.com/
Version 1.0
More information at http://strivinglife.com/words/post/Parsing-Yahoo!-Musics-Artist-Web-Services-with-C-and-LINQ-to-XML-Search-for-artists.aspx
Shared under a Creative Commons Attribution 3.0 United States License - http://creativecommons.org/licenses/by/3.0/us/
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Xml.Linq;
using System.Data;

namespace JamesRSkemp.WebServices {
    class YahooMusic {
        /// <summary>
        /// Key used to access Yahoo! Music Web services.
        /// </summary>
        private string AppId = "";

        /// <summary>
        /// Create a new YahooMusic object.
        /// </summary>
        /// <param name="appId">Application ID from Yahoo! Developer Network.</param>
        public YahooMusic(string appId) {
            if (appId.Trim() != "") {
                AppId = appId;
            } else {
                throw new Exception("You must pass a valid API identifier.");
            }
        }

        /// <summary>
        /// Return artists similar to the one passed, with a match percentage.
        /// </summary>
        /// <param name="artistName">The name of the artist to use for the request.</param>
        /// <returns>DataTable with artist names.</returns>
        public DataTable GetSimilarArtists(string artistName) {

            string requestUrl = "http://us.music.yahooapis.com/artist/v1/list/search/artist/"
                + System.Web.HttpUtility.UrlEncode(artistName.Trim())
                + "?appid=" + AppId + "&response=topsimilar";

            string serviceResponse = GetServiceResponse(requestUrl);

            var xmlResponse = XElement.Parse(serviceResponse);

            var artistsCount = from Artists in xmlResponse.Descendants("TopSimilarArtists").Descendants("Artist")
                               select new {
                                   name = Artists.Attribute("name").Value
                               };

            DataTable similarArtists = new DataTable();
            similarArtists.Columns.Add("Artist");

            if (artistsCount.Count() > 0) {
                DataRow artistsRow;

                foreach (var artist in artistsCount) {
                    artistsRow = similarArtists.NewRow();
                    artistsRow["Artist"] = artist.name;
                    similarArtists.Rows.Add(artistsRow);
                }
            }

            return similarArtists;
        }

        /// <summary>
        /// Gets the data from an HTTP request.
        /// </summary>
        /// <param name="requestUrl">The full Url of the request to make.</param>
        /// <returns>Returns a string with the text returned from the request.</returns>
        private string GetServiceResponse(string requestUrl) {
            string httpResponse = "";

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
            request.Timeout = 15000;
            HttpWebResponse response = null;
            StreamReader reader = null;

            try {
                response = (HttpWebResponse)request.GetResponse();
                reader = new StreamReader(response.GetResponseStream());

                httpResponse = reader.ReadToEnd();
            } finally {
                if (reader != null) {
                    reader.Close();
                }
                if (response != null) {
                    response.Close();
                }
            }

            return httpResponse;
        }
    }
}

One issue I do have is that I can't figure out how to get the count attribute off the root element that's returned. Try and search as I might, I can't figure it out.