Application Overview

In this chapter we build an example application—Margie's Travel Golf Reservation System—using the Microsoft .NET Framework. The Golf Reservation System is a tee-time registration application in which registered users can search for golf courses, view details on specific courses (tee descriptions, slope ratings, individual hole distances, pars, and handicaps), view available tee times at those courses, register for tee times, and view a list of previously registered tee times.

A production application of the the Golf Reservation System variety would normally provide much more functionality, but for the purposes of this book, the project allows us an under-the-hood view of .NET in action. It ties together course and user data, makes that data available through XML Web services, and displays it using the controller design pattern discussed in previous chapters.

Database Requirements

The database requirements for the Golf Reservation System's server-side component are relatively simple. We will use a Microsoft Access database to house all the course, golfer, tee information, and the tee times. Our goal is to keep the back-end of this system as simple as possible. The database will contain a small number of records for demonstration purposes, so a lightweight database management systems (DBMS) will be sufficient. If this application were meant to scale, we'd look into using a more sophisticated Relational Database Management System (RDBMS) such as the Microsoft SQL Server.

The XML Web services logic of the Golf Reservation System will not query the Access database directly. Instead, all data access will flow through a more abstract CourseDataSet class. The CourseDataSet will mimic the structure of the underlying DBMS and will provide quick and easy access to data from the application layer.

Using a DataSet to mask the underlying database has a number of advantages. First and foremost, it breaks the traditional ties that bind business logic to specific DBMS's. The Golf Reservation System's server-side component could be rewritten with a minimum amount of effort to support new database requirements. Second, direct in-memory DataSet access eliminates expensive boundary crossings to call into the database. Data can be retrieved quickly from the DataSet without the need for repetitive SQL queries. Finally reducing the load on the database engine frees it to operate more efficiently, enhancing the scalability of the application.

"Finder" XML Web services used for searching will create DataView objects to query the data contained in the CourseDataSet. Web Services can filter data by means of the DataView class's RowFilter property. Row filters use Expression objects to provide rich, SQL-like selection capability.

The server will implement a series of DataAdapter classes to handle all marshaling of data to and from the database. There will be a single DataAdapter class for each database table. These adapters will work together to load the table data into a consolidated data set. Data updates will require the following three separate steps:

  1. The business logic will update the CourseDataSet with the new record. This action will result in a new, removed, or updated data row whose state is reflected in the object's RowState property.
  2. The business logic will call the Update( ) method on the appropriate data adapter. The adapter will analyze the data set at this time and determine what action, if any, to perform to synchronize the underlying database tables.
  3. The business logic will call the AcceptChanges( ) method on the CourseDataSet object. This will return the dataset to a stable state and will reload any new information from the database.

Business Logic Requirements

The Golf Reservation System server business logic consists of all the object/database interactions that happen underneath the XML Web services facade. Database tables in the application are manipulated indirectly via a layer of high-level business objects. The class definitions for these objects are based directly on the underlying database schema.

Business Object C# Class Definitions

The application provides C# classes for each object represented by a database row as well as classes for commonly used containable business objects that have no single table relationship, such as an address. Each class contains traditional methods in getters and setters and in most cases multiple constructor methods.

Not every class in the application mirrors a database table as does the GolfCourse class. The same will likely hold true with any application you build inside the .NET Framework. For example, the fact that the application contains an address class as an address object can be useful because, at least within our application, it relates to and holds requirements for the same properties and methods across multiple business entities (both a golfer and a golf course have addresses). Obviously, one goal of a .NET application is code reuse, and although this is a simple example, it's a good example nonetheless.

Table 9-1 contains the business objects in the Golf Reservation System application.

Table 9-1 Business Entities in the Golf Reservation System Server Application
Class File Description


The Address class defines a generic address structure. Instances of this class are referenced by the GolfCourse and Golfer objects.


The GolfCourse class contains general properties describing a golf course. All information regarding holes, yardages, pars, and so forth are delegated to helper classes.


The Golfer class defines a golfer in the system. Names, addresses, and security information are all found in this class.


The Hole class defines a hole on a golf course. Hole objects contain properties such as par, distance, and handicap. Each set of tees (for example, red, white, blue) on the golf course has 18 unique hole instance.


The Tee class defines a set of tees throughout the course. Properties in the class include slope, distance, a description, and an array of hole objects.


The TeeTime class defines a unique tee time for a specific golf course on a certain date. Properties include the golf course ID, the golfer ID, and the date and time.

Web Services

The application contains only one XML Web service, conveniently named GolfCourseService. Numerous XML Web methods, however, are available within this lone service. The methods necessary for the TeeTimes application vary from search helpers to everyday "findById" methods.

GolfCourseService, like all XML Web services, is responsible for masking business object design complexities and particulars. The developer that needs to call into and retrieve data from Web methods need not know whether a table of addresses is in the database. The application calls into the GolfCourseService XML Web service via SOAP requests and receives SOAP responses. The .NET Framework, though, handles the complexities of creating, sending, receiving, and parsing the SOAP documents.

Browsing to an XML Web service with a Web browser results in a detailed description of the XML Web service, what methods it provides, and how to call into those methods using the supported protocols. Figure 9-1 shows the GolfCourseService called in this manner.

Figure 9-1 Browsing to an XML Web service provides detailed information about the methods provided.

Clicking a specific method (see Figure 9-2) offers a detailed description of that method and a form to invoke it, given your inputs. Note that submitting the form invokes the method and will perform the actions of that method as if it were called from an application If the method results in a new database insert, submitting this form will do the same. Also detailed on the method description page is the protocol syntax request and response for SOAP calls, HTTP POST, and HTTP GET.

Figure 9-2 Clicking a Web method offers a method description and protocol syntax for invoking the method.

As detailed in Figure 9-1, the GolfCourseService offers the following Web methods, listed here by method signatureP:

public GolfCourse[] FindAll()
public GolfCourse[] FindGeneric(String[] fields, String[] values)
public GolfCourse GetCourseDetail(String id)
public GolfCourse AddCourse(String name, String description, 
String price, String streetAddress, String city, String state, String
postalCode, String country, String telephone) public GolfCourse AddTee(int courseId, String description, float slope) public GolfCourse AddHole(int teeId, int handicap, int length, int hole, int par) public TeeTime AddTeeTime(int courseId, int golfer, DateTime date, DateTime time) public TeeTime[] FindTeeTimesByGolfer(int golferId) public Golfer AddGolfer(String firstName, String lastName,
String streetAddress, String city, String state, String postalCode,
String country, String email, String phone, String username, String password) public Golfer FindGolferById(int golferId) public Golfer ValidateLogin(String username, String password) public TeeTime[] FindTeeTimesByDate(int courseId, DateTime date) public TeeTime[] FindTeeTimesByDateRange(int courseId, DateTime
startDate, DateTime endDate)

These Web methods and the classes behind them make up the server-side component of our application and represent the proxy necessary for other applications to interact with and manipulate the Golf Reservation System business logic. We will break down these Web methods and the Golf Reservation System server business logic behind them in more detail later in the chapter.

User Requirements

A good division of labor between developer and designer is rarely achieved when rich UI are required for sophisticated applications. The more business logic an application developer can mask from the UI developer, the better. Combining XML Web services in the .NET Framework with the controller design pattern, though, results in a further separation of the duties of developers and designers. This is true not only because the controller XSLT skin is completely responsible for formatting controller result XML, but also because developer duties can be divided between server and client. The results are truly distributed applications in that one developer provides the XML Web services, perhaps in conjunction with a UI, while another developer, interested only in manipulating those XML Web services, builds an entirely separate client application.

Imagine the Golf Reservation System server application as a stand-alone service provided by a conglomeration of golf courses. Multiple Internet applications could call into those services and format and manipulate data as they saw fit: one client application might use the GolfCourseService only to retrieve data, while another might retrieve golfer information from the GolfCourseService, caring nothing about the course data also available.

Although the application is tailored to a specific client—one that allows validated users to register for tee times—the Web methods could be designed modeling only the data behind them. This approach would provide an XML Web service interface for retrieving the data published on the Internet that was not tailored to a specific client application design, but instead provided abstractions on a complex data store.