When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article
Jobs

ASP ASP.NET ASP FAQs Message Board Feedback ASP Jobs
 
Print this Page!
Published: Wednesday, November 12, 2003

Building an NBA Team Standings Web Service

By Scott Mitchell


Introduction


If you are a regular visitor to 4Guys you are likely aware of an ongoing article series I am writing, An Extensive Examination of Web Services, which looks at the ins and outs of .NET Web services. That article series looks at the technologies that makeup Web services, how to create and consume Web services, the Web Service Enhancements (WSE) standards, and so on. What the article series omits, is examples of real-world uses of Web services.

- continued -

In this article we will look not at what Web services are, but at where they can be used. We'll start by examining a fun Web service, one that returns a list of NBA teams with their win/loss records, ordered in terms of the conference standings.

NBA standings...

Getting the Information for the NBA Team Standings


I, like many other NBA fans, run a blog (NBAWebLog.com) dedicated to talking about the latest NBA teams and news. The other day I decided it would be nice to be able to display on my blog the current NBA standings. Essentially, I wanted something like the screenshot to the right to be permanently posted on my blog. Specifically, I wanted to be able to display the latest NBA standings without having to do anything on my end. That is, I didn't want to have to maintain some standings database. I wanted the results to be automatically updated periodically. Finally, I wanted to be able to share this functionality with other NBA bloggers.

Fortunately there are a number of NBA Web sites - like NBA.com, ESPN.com, Sportsline.com, and many others - that provide a Web page that lists the latest NBA standings. Unfortunately, none of these sites offer Web service accessibility to the NBA standings. This left me with one option - screen scraping. (Screen scraping is having an ASP or ASP.NET page make an HTTP request to a remote Web server to get its HTML. This HTML is then parsed for the "interesting" information, such as the NBA team standings in this case.) Screen scraping is possible in ASP.NET via the WebClient class, as described in an earlier article on mine, Screen Scrapes in ASP.NET.

I chose to use the standings at NBA.com, although the standings from any of the competing NBA Web sites would have done. Once the HTML data is slurped down, it needs to be parsed to extract the team name and their wins and loses. To accomplish this feat I used regular expressions. Going into the specific patterns used is a bit beyond the scope of this article. If you are interested, check out the code at the end of this article; for more information on regular expressions, be sure to visit the Regular Expressions FAQ Category.

Creating an Object Model to Represent Team Information


Since there were no Web services I could find that returned the latest NBA standings, I decided that I needed to create my own. (Putting this functionality in a Web service, instead of in an individual ASP.NET Web page, would give other NBA bloggers access to this data.) As we just discussed, with screen scraping I could get the NBA teams and their win/loss records, but how should this data be returned from the Web service to the application consuming the Web service?

I decided to create the following classes to represent the teams' standings:

  • Team - represents a single team. Has three properties: Name, Wins, and Loses.
  • TeamList - represents a set of teams.

The Web service, when invoked, returns a TeamList instance that contains a list of the teams for a specified conference (there are two conferences in the NBA - the Eastern conference and the Western conference). The teams are ordered by their conference rankings.

Examining the Web Service's Methods


The Web service contains one publicly-accessible method, GetStandings(conference), where conference can is an enumeration with two values: Eastern and Western. The method returns a TeamList object. This method's code - shown below - is very simple, as it delegates the screen scraping to a private helper method:

<WebMethod()> _
Public Function GetStandings(ByVal confChoice As ConferenceEnum) As TeamList
    'First, screen scrape the data from NBA.com's Web site
    If confChoice = ConferenceEnum.Eastern Then
        Return GetStandings()(0)
    Else
        Return GetStandings()(1)
    End If
End Function

Notice that GetStandings(conference) simply calls an overloaded form of GetStandings(), one that takes no input parameters. This overloaded form returns a two-element array of type TeamList, with the first element the teams in the Eastern conference and the second element the teams in the Western conference. So, if GetStandings(conference) is called with the Eastern conference enumeration value passed in, the first element of the two-element array returned by GetStandings() is returned; similarly, if Western is passed in, the second element is returned.

The germane code for GetStandings() is shown below. Note that is uses the ASP.NET data cache to cache the results of the screen scrape.

Private Function GetStandings() As TeamList()
    'See if the standings are in the cache...
    If Not HttpContext.Current.Cache.Get("standingsList") Is Nothing Then
      Return CType(HttpContext.Current.Cache.Get("standingsList"), TeamList())
    End If

    '... do the screen scraping
    Code removed for brevity...

    For Each match As Match In matches
        'Get the team name
        'Parsing the team and record out of the HTML 
        Some code removed for brevity!
        Dim tName As String = 'Parse using regex
        Dim wins As Integer = 'Parse using regex
        Dim loses As Integer = 'Parse using regex

        eastTeamCount += 1
        If eastTeamCount <= EASTTEAMS Then
            east.Add(New Team(tName, wins, loses))
        Else
            west.Add(New Team(tName, wins, loses))
        End If
    Next

    'Return the east/west as a two-element array
    Dim lists(1) As TeamList
    lists(0) = east
    lists(1) = west

    'Add lists to the cache
    HttpContext.Current.Cache.Insert("standingsList", lists, Nothing, _
                                     DateTime.Now.AddHours(4), TimeSpan.Zero)

    Return lists
End Function

The Web service is available at http://nbaweblog.com/nba/Standings.asmx. Since not all NBA bloggers have experience with consuming a Web service, I also created a simple ASP.NET Web page (http://nbaweblog.com/nba/standings.aspx) that will display the standings (discussed in the next section). This Web page, then, can be displayed at a blogger's site using an <iframe>.

Consuming the Web Service in an ASP.NET Web Page


Consuming the Web service is a breeze. As discussed in An Extensive Examination of Web Services: Part 3, consuming a Web service with Visual Studio .NET is as simple as creating a proxy class and then instantiating the proxy class and calling the appropriate Web service's method(s). Since the Web service method returns a TeamList object, this object can be bound to the DataSource of a data Web control, if desired. (Note that the proxy class created was named NBA.Standings.)

'The germane code-behind class portion...
Private Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    Dim proxy As NBA.Standings = New NBA.Standings
    EastStandings.DataSource = proxy.GetStandings(NBA.ConferenceEnum.Eastern)
    EastStandings.DataBind()
End Sub

'The HTML portion
<asp:DataGrid id="EastStandings" runat="server" AutoGenerateColumns="False" ...>
   <Columns>
      <asp:TemplateColumn HeaderText="Team">                  
         <ItemTemplate>
			(<%# Container.ItemIndex %>)
            <%# Container.DataItem.Name %>
         </ItemTemplate>
      </asp:TemplateColumn>
      <asp:TemplateColumn HeaderText="Record">
         <ItemStyle HorizontalAlign="Center"></ItemStyle>
         <ItemTemplate>
            <%# Container.DataItem.Wins %>-<%# Container.DataItem.Loses %>
         </ItemTemplate>
      </asp:TemplateColumn>
   </Columns>
</asp:DataGrid>

Conclusion


In this article we looked at how to create and consume a Web service that will return the standings of the NBA teams on a conference-by-conference basis. The Web service works by periodically screen scraping the NBA team standings at NBA.com. This allows for a relatively up-to-date listing of the NBA team records, ordered by the teams' rankings.

Happy Programming!

  • By Scott Mitchell


    Attachments:


  • Download the complete code (in ZIP format)



  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article