Developers must realize there is more to programming than simple code. This two-part series addresses the important issue of application architecture using an N-tier approach. The first part is a brief introduction to the theoretical aspects, including the understanding of certain basic concepts. The second part shows how to create a flexible and reusable application for distribution to any number of client interfaces. Technologies used consist of .NET Beta 2 (including C#, .NET Web Services, symmetric encryption), Visual Basic 6, the Microsoft SOAP Toolkit V2 SP2, and basic interoperability [ability to communicate with each other] between Web Services in .NET and the Microsoft SOAP Toolkit. None of these discussions (unless otherwise indicated) specify anything to do with the physical location of each layer. They often are on separate physical machines, but can be isolated to a single machine.
For starters, this article uses the terms "tier" and "layer" synonymously. In the term "N-tier," "N" implies any number, like 2-tier, or 4-tier, basically any number of distinct tiers used in your architecture.
"Tier" can be defined as "one of two or more rows, levels, or ranks arranged one above another" (see http://www.m-w.com/cgi-bin/dictionary?Tier). So from this, we get an adapted definition of the understanding of what N-tier means and how it relates to our application architecture: "Any number of levels arranged above another, each serving distinct and separate tasks." To gain a better understanding of what is meant, let's take a look at a typical N-tier model (see Figure 1.1).
Figure 1.1 A Typical N-Tier Model
Since this has been deemed the Age of Information, and since all information needs to be stored, the Data Tier described above is usually an essential part. Developing a system without a data tier is possible, but I think for most applications the data tier should exist. So what is this layer? Basically, it is your Database Management System (DBMS) -- SQL Server, Access, Oracle, MySql, plain text (or binary) files, whatever you like. This tier can be as complex and comprehensive as high-end products such as SQL Server and Oracle, which do include the things like query optimization, indexing, etc., all the way down to the simplistic plain text files (and the engine to read and search these files). Some more well-known formats of structured, plain text files include CSV, XML, etc.. Notice how this layer is only intended to deal with the storage and retrieval of information. It doesn't care about how you plan on manipulating or delivering this data. This also should include your stored procedures. Do not place business logic in here, no matter how tempting.
The Presentation Logic Tier
Let's jump to the Presentation Logic Layer in Figure 1.1. You probably are familiar with this layer; it consists of our standard ASP documents, Windows forms, etc. This is the layer that provides an interface for the end user into your application. That is, it works with the results/output of the Business Tier to handle the transformation into something usable and readable by the end user. It has come to my attention that most applications have been developed for the Web with this layer talking directly to the Data Access Layer and not even implementing the Business Tier. Sometimes the Business Layer is not kept separated from the other two layers. Some applications are not consistent with the separation of these layers, and it's important that they are kept separate. A lot of developers will simply throw some SQL in their ASP (using ADO), connect to their database, get the recordset, and loop in their ASP to output the result. This is usually a very bad idea. I will discuss why later.
The Proxy Tier and the Distributed Logic
There's also that little, obscure Proxy Tier. "Proxy" by definition is "a person [object] authorized to act for another" (see http://www.m-w.com/cgi-bin/dictionary?Proxy). This "object," in our context, is referring to any sort of code that is performing the actions for something else (the client). The key part of this definition is "act for another." The Proxy Layer is "acting" on behalf of the Distributed Logic layer (or end-user's requests) to provide access to the next tier, the Business Tier. Why would anyone ever need this? This facilitates our need for distributed computing. Basically it comes down to you choosing some standard method of communication between these two entities. That is, "how can the client talk to the remote server?"
This is where we find the need for the Simple Object Access Protocol (SOAP). SOAP is a very simple method for doing this. Without too many details, SOAP could be considered a standard (protocol) for accessing remote objects. It provides a way in which to have two machines "talking" or "communicating" with each other. (Common Object Request Broker Architecture [CORBA], Remote Method Invocation [RMI], Distributed Component Object Model [DCOM], SOAP, etc., all basically serve the same function.)
The Client Interface
In this section of Figure 1.1 we notice that the end-user presentation (Windows forms, etc.) is connected directly to the Business Tier. A good example of this would be your applications over the Local Area Network (LAN). This is your typical, nondistributed, client-server application. Also notice that it extends over and on top of the Distributed Logic layer. This is intended to demonstrate how you could use SOAP (or some other type of distributed-computing messaging protocol) on the client to communicate with the server and have those requests be transformed into something readable and usable for the end user.
The Business Tier
This is basically where the brains of your application reside; it contains things like the business rules, data manipulation, etc. For example, if you're creating a search engine and you want to rate/weight each matching item based on some custom criteria (say a quality rating and number of times a keyword was found in the result), place this logic at this layer. This layer does NOT know anything about HTML, nor does it output it. It does NOT care about ADO or SQL, and it shouldn't have any code to access the database or the like. Those tasks are assigned to each corresponding layer above or below it.
We must gain a very basic understanding of Object-Oriented Programming (OOP) at this time. Take time to read over http://searchwin2000.techtarget.com/sDefinition/0,,sid1_gci212681,00.html and make sure you understand the important benefits of OOP. To clarify, let's look at another example, such as a shopping cart application. Think in terms of basic objects. We create an object to represent each product for sale. This Product object has the standard property getters and setters: getSize, getColor, setSize, setColor, etc. It is a super simple implementation of any generic product. Internally, it ONLY knows how to return information (getters) and understands how it can validate the data you pump into it (ONLY for its limited use). It is self-contained (encapsulation). The key here is to encapsulate all the logic related to the generic product within this object. If you ask it to "getPrice," it will return the price of the single item it represents. Also if you instruct it to "validate" or "save," it has the brains to be able to handle this, return any errors, etc.
We can plug this Product object into another object, a "Cart" object. This cart can contain and handle many Product objects. It also has getters and setters, but obviously on a more global scale. You can do something like "for each product in myCart", and enumerate (loop through) each product within. (For more information on enumeration, refer to http://www.m-w.com/cgi-bin/dictionary?enumeration.) Now, when you call "getPrice" for the Cart object, it knows that it must enumerate each product that it has, add up the price for each, and return that single total. When we fire the "saveCart" method, it will loop for each "product" and call its "saveProduct" method, which will then hit the Data Access Tier objects and methods to persist itself over to the Data Tier.
We could also take our simple Product object, and plug it into our "Sale" object. This Sale object contains all of the items that are available for a particular sale. And the Sale object can be used for things like representing all the items on sale at a given outlet or the like. I'm sure you are beginning to understand the advantage of using an OOP environment.
Data Access Tier
This layer is where you will write some generic methods to interface with your data. For example, we will write a method for creating and opening a Connection object (internal), and another for creating and using a Command object, along with a stored procedure (with or without a return value), etc. It will also have some specific methods, such as "saveProduct," so that when the Product object calls it with the appropriate data, it can persist it to the Data Tier. This Data Layer, obviously, contains no data business rules or data manipulation/transformation logic. It is merely a reusable interface to the database.
Conclusions
In all of the systems that I have been able to dig my dirty little hands into, I have rarely ever seen both the Business Tier and Data Access Tiers used. I mostly combine the two tiers. Allow the Business Layer to talk directly to the Data Layer, and do not bother with the Data Access Layer. To justify this, we are all developing on Internet time, and the last time I looked, it's still going at about 3 to 4 times faster than normal time, which means we are expected to also work and produce at the same rate. The bottom line is reducing the time to market. In my opinion, writing this Data Access Tier, which is simply abstracting the Data Tier, is overkill, and ADO can be considered as this Data Access Layer. It provides us with the interface directly. We still keep all SQL in the Data Tier (stored procedures), but no business rules should be kept here.
Of course, the more tiers you add, the more performance is affected. The client hits "Save Cart" on their Web-enabled phone, it hits the Business Tier to call the "Cart" "saveCart," which calls the products "save," which goes either directly to the database or goes through the Data Access Layer and finally persists into the database. This path does affect performance. It is up to the application architect (you) to know and understand this, and all other factors affecting the system, and be able to make a good decision on how to develop it at this level. This decision is usually pretty easily made, depending on the amount of work and documentation that was produced from the analysis phase.
We all now know how to do this logically. Let's explain the why. A good example is to look at the Presentation Logic Tier. Notice that many of its sections --the Web, the Proxy Tier, and the Client Interface -- all sit directly on top of the Business Tier. We gain the advantage of not needing to redo any code from that Business Tier all the way to the database. Write it once, and plug into it from anywhere.
Now say you're using SQL Server and you don't want to pay Microsoft's prices anymore, and you decide to pay Oracle's instead. So, with this approach you could easily port the Data Layer over to the new DBMS and touch up some of the code in the Data Access Layer to use the new system. This should be a very minimal touch-up. The whole point is to allow you to plug each layer in and out (very modular) without too many hassles and without limiting the technology used at each tier.
Another example would be that we initially develop our entire system using VB (COM) and ASP, and now we want to push it over to our friendly VB .NET or C#. It is just a matter of porting the code over at each layer (phased approach), and voila, it's done. (Microsoft has given us the ability for interop between classic COM and .NET.) We can upgrade each layer separately (with minor hurdles) on an as-needed basis.
About the Author
Robert Chartier has worked in the information technologies field for more than 7 years. While studying at college he began his career working as a software and hardware technician at the college, supporting a user base of thousands of students and hundreds of instructors. Once his college days were finished he moved on to full-time studies at a university in the lower mainland of British Columbia, and landed a full-time job developing large projects for distribution on many platforms, mediums, and languages.
Next, he moved onto Stockgroup, where he was able to tap into the Internet development market on a larger and more focused scale. In his spare time he began writing and producing content for developer-specific sites focusing on Microsoft technologies (ASP, COM/COM+, etc.). He has also been a part of many open forums on cutting-edge technologies, such as the .NET Framework and Web Services (SOAP), and has been invited to speak at large developer conferences and contribute to many technical publications.
His next step was to take a position with a large B2B training marketplace, Thinq.com. At Thinq he developed many tools, including a very comprehensive search engine with custom business rules for weighting, sorting, and analysis (COM+). This led him into strong development with beta versions of Commerce Server 2000 and BizTalk Server 2000.
His next opportunity included a large Internet development effort using technologies such as JSP (Java Beans, J2EE), Oracle, WebLogic, etc. Robert Chartier can be reached at rob@aspfree.com.
This article is the second in a two-part series regarding developing the client server model using an N-tier approach. Throughout this article, I will be making many references to Part 1 (see http://www.15seconds.com/issue/011023.htm). You might consider rereading it before proceeding.
The purpose of this article is to take the theoretical explanation given in Part 1, and show you how to apply it to your future applications. The example I have chosen is a fairly simple one, an address book. I will walk you through the development and integration of an N-tier model, showing you how it can be easy to implement a new Database Management System (DBMS) (unplug your current database and plug in a new one), and finally how to take your existing middle tier and deploy it on to a new platform (Web Services). My platform of choice is the .NET Framework Beta 2, using Visual Studio Release Candidate 1 (RC1), using the new .NET language, C#. It is important for you to not focus on the actual code of this article. That is irrelevant. Instead, put more focus on the way in which I developed and separated each tier of the application. You must also realize that I'm not going to formally walk you through any distinct stages of an application systems development life cycle, just the bare bones needed for the completion of this application. I will also not cover extensive error-handling routines, and security is always a major issue with any application so I have put in place only the minimum needed for this article. Please consult one of the many resources regarding these features and implement them at your leisure.
Here's a bit of information about what we are going to develop.
A. The Business Portion of the Application:
- It is going to be an address book.
- All users must login in order to gain access to their address book.
- An address book has to have one owner, but can be owned and administrated by many.
- An owner is a contact of the address book.
- An address book can have one to many contacts.
- Each address book has a name and a description.
- Each user can have and belong to many address books.
- A contact can only appear once in any address book.
B. The Implementation of the Application:
- It is going to be available over normal HTTP (a Web site).
- It is expected to be available over eXtensible Markup Language (XML) Web Services (via HTTP).
- We do initial development with Microsoft Access 2000.
- We want to be able to easily upgrade our database from Access to SQL Server 2K after development is done.
The rest of this article will work down from our Data Tier to the Presentation tier, in that order.
Section 2: Defining and Creating the Data Tier
Think of the Data Tier as your DBMS (a.k.a. Access or SQL Server). We must create our database so that it will solve our requirements listed above and at the same time not limit our future development. Usually the database administrator does this work, but since this is a fairly small application, we will assume that role and throw the database together.
We start by opening up Access and creating a blank database. I called it "addressbook.mdb." Let's begin with the Contact List that will represent your standard user. I decided to use the Email Address as our Primary Key1 (PK) (explanation footnoted at end of section). (I have included the Access database as a part of the download for this article).
Figure 2.1 Contacts Table
Key | name | type | size | defaultvalue | required | zero length | indexed |
PK | emailaddress | text | 150 |
| yes | no | yes |
| password | text | 10 |
| no | yes | yes, duplicates ok |
| first | text | 50 |
| no | yes | no |
| last | text | 50 |
| no | yes | no |
| areacode | Number | Integer | 0 | no |
| no |
| phone | Number | Long Integer | 0 | no |
| no |
| fax | Number | Long Integer | 0 | no |
| no |
| address | text | 200 |
| no | yes | no |
| address1 | text | 200 |
| no | yes | no |
city | text | 50 | no | yes | no | ||
| zip | text | 10 |
| no | yes | no |
| state | text | 75 |
| no | yes | no |
| country | text | 50 |
| no | yes | no |
The second table we will throw together is the Address Book table. This is going to represent each individual address book in the system.
Figure 2.2 AddressBook Table
Key | name | type | size | defaultvalue | required | zero length | indexed |
PK | bookid | autonumber | Long Integer |
| yes | no | yes, no duplicates |
| name | text | 50 |
| yes | no | yes, duplicates ok |
| description | text | 250 |
| no | yes | no |
If we take a look at both of these tables, you will see that the there is no relationship between them. What we must do is define what is called an "intersection table." This is simply a table that will contain both of the PKs from each table, which is used to relate each table to each other. We use this "intersection" to assign a contact to an address book, for example, and other things.
Figure 2.3 AddressBookContacts Table
Key | name | type | size | defaultvalue | required | zero length | indexed |
FK (PK) | bookid | number | Long Integer | 0 | yes |
| yes, duplicates ok |
FK (PK) | emailaddress | text | 150 |
| yes | no | yes, duplicates ok |
| relationship | Number | byte | 0 | yes |
| no |
Let me run you through each of the fields for this table. The "bookid" field is the PK from the AddressBook table, represented in this table as a Foreign Key1 (FK). The "emailaddress" field is the PK from the Contacts table and is also represented in this table as a FK. Together, these two make up the PK for this table. This allows us to have any number of contacts belonging to any address book. It also allows us to not allow a contact to appear more than once in a given address book. The last field,"relationship", is used to indicate the relationship between these records. Let's create a new table to describe these relationships. Figure 2.3.1 Relationship Table
Key | name | type | size | defaultvalue | required | zero length | indexed |
PK | id | AutoNumber | Long Integer |
|
|
| yes, no duplicates |
| name | text | 100 |
| yes | no | no |
| description | text | 255 |
| no | yes | no |
You may be asking yourself what exactly is a relationship and why do we need it? A relationship, in this case, is how we relate the specific contact to the address book. An example would be "Owner", or "Administrator", or "Contact". Here is some sample data for this table:
Figure 2.4 Sample Relationship Data
id | name | description |
1 | Owner | An owner of this address book |
2 | Contact | A contact belonging to this address book |
3 | Administrator | An administrator of the address book. These users can edit, add, and remove contacts of the book, but cannot delete the entire book itself. |
To the question "Why do we need this?", I say take a look back at our requirements, specifically A3. It states "An Address Book has to have one owner, but can be owned and administrated by many." This will allow us to enable the system to have any address book with a designated owner, but also an administrator who would have some of the same abilities as the owner. This introduces a model where we can grant access to different users to perform different actions to our address books and contacts.All we need is to have at least one owner defined for each address book, and the rest can be optionally used in order to start associating contacts to each address book. This will also allow us to define more roles in the system and allow for contacts to have different sets of access to any given address book. I have found this to be a very flexible model.
1 Keys -- primary and foreign -- They are used in establishing relationships between records. The primary key in a table is the data field in each record, which is guaranteed to be unique and which can therefore be used to establish relationships between each record in that table and other records in other tables. The foreign key in a table is a primary key for records in another table. Foreign key values don't have to be unique within a table, thus allowing a one- (primary key) -to-many (foreign key) relationship to exist (see http://magni.grainger.uiuc.edu/lis450ds/introsql.htm).
Section 3: Setting Up the Development Environment
Let's start the Visual Studio.NET development environment and create a new ASP.NET application. I chose to start out with an ASP.NET application because our primary interface for this application will be through the Web and ASP.NET. In the Visual Studio.NET start page, we first hit the "New Project" (1) button. Personally, I prefer using C# rather than Visual Basic so I chose "Visual C# Projects (2), and using a "ASP.NET Web Application" (3), I created the application at the location http://localhost/AddressBook (4).
Figure 3.1 Creating the ASP.NET Application
(Click here to generate larger version.)
The next application we will add to our solution will be used to contain the Data Access tier. In the Solution Explorer, right click the "AddressBook" Solution, choose "Add", "New Project". This new project will be a reusable C# (1), Class Library (2), with the name "DataAccess" (3).
Figure 3.2 Adding the Data Access Tier
(Click here to generate larger version.)
Change the name of the Class File Name. This can be found in the Solution Explorer, Click the "Class1.cs" file, and view the Properties pane. You will see the "File Name" attribute. Rename it "AddressBookDA.cs".
The next application we will add is our Business tier. Follow the same procedure as we did to add the Data Access tier, but give it the name "Business" (3). Don't forget to change the name of its default class to "AddressBookBiz.cs". And finally, since we wish to expose this entire application over Web Services (HTTP), we will also add in a C# ASP.NET Web Service (3) application. Make sure you change its location to http://localhost/AddressBookService. This time rename the "Service1.asmx" file to "AddressBook.asmx".
The next step will be to set up the dependencies for each application. See Figure 1.1 at http://www.15seconds.com/issue/011023.htm and the dependencies will become pretty clear. The Business tier will depend on the Data Access tier, and above that the Presentation tier (ASP.NET application, and Web Services application) will depend on the Business tier.
Right click on the "Business" application, and choose "Add Reference", "Projects" tab, and then select the "DataAccess" application. Hit the "Select" button to add it to the "Select Components" section. Repeat this process for both the "Address Book" application and the "AddressBookService" application, but for each of these, choose the "Business" project. The next few steps will guide you through the setup for each application.
Section 4: Creating the Data Access Tier
Looking back at Part 1 of this article (see http://www.15seconds.com/issue/011023.htm), we see that the Data Access tier is used to simply interface with our database. It contains no business logic or constraints. It merely provides a way in which to interact with the database (Insert, Select, Delete, and Update). In other words, it allows us to create a set of useful and specific routines to be able to perform those four actions on our tables.
For this project, we need to create a namespace (see http://stylusinc.com/website/c_sharp.htm#Namespaces) that will encompass our Data Access tier. You will see, later in the article, that we will also be creating separate namespaces for the Business tier, etc...
Most of this code is standard. To reiterate, the most important thing to remember for this tier is that it is a set of specific methods that are used to perform all of the database interactions. It must NOT contain any business logic or presentation items. If you wish, take a look in the AddressBookDA.cs file (part of download accompanying this article) to see what methods I exposed and how I perform the database operations with it now. Also pay close attention to how this has been created for an Access database. Since each DBMS we use in our careers has different capabilities, our Data Access tier will differ slightly for each. One of the nicest features of an N-tier architecture is the ability to easily switch this layer out when a new DBMS is put in place. I will develop this application based on an Access database. When the time comes to upgrade to SQL Server, or another quality DBMS, we will only need to modify our Data Access tier and the rest of the application will function unchanged. This means no more rooting though thousands of lines of code just to upgrade our in-line SQL to stored procedures.
Section 5: Creating the Business Tier
If you recall, the Business tier is where we place all of our custom business logic. For this address book application it will contain logic such as all of the items we find in Section 1, List A of our requirements. There will be no connections to any database and no presentation-specific code.
In our Business tier we must expose a set of methods that will be useful and that will solve the business rules. It is also important to remember that these objects can be stateful for the lifetime of that specific object instance, but not stateful for the entire application's existence.
We will create two separate classes within this AddressBookBiz namespace, one to represent an actual address book and another to represent our contacts.
Let's drill down for each object and determine the methods and properties that we will expose.
Figure 5.1 List of Objects' Properties and Methods
AddressBook Object |
|
|
|
Properties |
|
|
|
Name | Get | Set | Public |
bookid | yes | no | yes |
name | yes | yes | yes |
description | yes | yes | yes |
relationshiplist* | yes | no | yes |
|
|
|
|
Methods |
|
|
|
Name | Description | Parameters | Public |
Default Constructor | Creates an empty instance of the object | none | yes |
Overloaded Constructor | Loads up the appropriate address book | bookid | yes |
Overloaded Constructor | Creates a new address book | name, description Contact | yes |
loadAddressBook | Internal method to load up the book. Called by other methods | bookid | no |
CanView | Used to determine if the supplied user can view the book | emailaddress | yes |
GetContactsDataSet | Gets a DataSet of the contacts for the Address object | none | yes |
AddNewContact | Add a new contact to the current Address object | Contact | yes |
getLastError | Simply returns the last error message | none | yes |
Validate | Validates itself | none | yes |
Save | Persists the current Address book to the database | none | yes |
AddContact | Adds a contact to the current address book | Contact, Relationship | yes |
|
| ||
|
| ||
Contact Object |
|
|
|
Properties |
|
|
|
Name | Get | Set | Public |
emailaddress | yes | no | yes |
password | yes | yes | yes |
first | yes | yes | yes |
last | yes | yes | yes |
areacode | yes | yes | yes |
phone | yes | yes | yes |
fax | yes | yes | yes |
address | yes | yes | yes |
address1 | yes | yes | yes |
city | yes | yes | yes |
zip | yes | yes | yes |
state | yes | yes | yes |
country | yes | yes | yes |
|
|
|
|
Methods |
|
|
|
Name | Description | Parameters | Public |
Default Constructor | Creates an empty instance of the object | none | yes |
Overloaded Constructor | Loads up the appropriate user (login) | emailaddress, password | yes |
Overloaded Constructor | Loads up the appropriate user | emailaddress | yes |
saveContact | save the specific contact | none | no |
isUserValid | Determines if the supplied user is valid or not | none | yes |
getAddressBooks | Returns all of the user's address books (not preloaded) | emailaddress | yes |
getLastError | Simply returns the last error message | none | yes |
Validate | Validates itself | none | yes |
Save | Persists the current contact to the database (if we can) | none | yes |
* I’ve decided to place this method, which merely returns a list of the available relationships, in the Address Book | |||
object in order to keep this article short and simple. Normally you would probably make the decision to create | |||
a new, separate object that would perform the needed relationship actions. | |||
** Since each Address Book object will contain a collection of Contact Objects, our Contact Pointer is merely | |||
a reference to the current contact in our list. |
At this time, review my version of "AddressBookBiz.cs" (part of download). Pay attention to the Save method, and how it is first calling its own Validate method in order to ensure that it conforms to the established rules. (This will validate the object at the object level). Calling the Save method in the address book will validate the current address book, and then it will also call the Save method on each of its contacts, which will also call its own Validate method. In the end, if everything validates fine, it will all be persisted to the database.
I want to quickly review what I did regarding security. In order to represent the current user (who is logged in), I needed a way to easily represent that user based on their login information. I used a basic symmetrical encryption algorithm (borrowed from http://www.4guysfromrolla.com/webtech/090501-1.shtml). This Namespace is based on the Cryptography base classes within .NET. To integrate it within our "business" application, I only needed to add it to our application (see previous examples on how to do this). Now, when the user is logged in, or authenticated against our database, I take their email address and their password, and join them into a single string, and then apply the encryption algorithm. This generates a Universal Unique (user) IDentifier (UUID). And when I need to determine who this UUID belongs to, I simply unencrypt the UUID, and then split the string back into the email address and the password and re-authenticate against my database. I created this in this fashion in order to simplify the security issues for this article. More help on cryptography can be found at http://www.demcom.com/english/steganos/htmlhelp/IDH_TECH_CRYPTOGRAPHY.htm or on many other Internet sites.
I have completed most of the Business tier for you. I have left out some validation within each of the Property Get/Set methods. You should conform each method to what you expect for this application. For example, the Area Code property could be limited to only valid area codes (001 to 999), or the Country property could be limited to only a set of ISO-standard country codes. This has offered you a place to put all of your server-sided data validation. Another thing you may consider is looking into the validation tools within the .NET architecture. There are plenty of examples of this available on the Internet, just as long as you always keep in mind that validation MUST be performed on the server, and in your middle tier. You can optionally add it on the client with JavaScript or whatever is specific to your deployment platform. Adding validation to a single interface on the Presentation tier will only enable that specific interface to the system to take advantage of that validation. Your other interfaces will not be able to take advantage of this.
Section 6: The ASP.NET Presentation Interface
Now that we have a working infrastructure for our Address Book application, it is usually a small task to wrap this functionality within any Presentation interface we wish. It is only a matter of hooking into our Business tier. In order to keep things simple I have created a minimal amount of forms for you to review, each with a slim interface with no fancy pictures or formatting (my excuse -and apologies-- for the ugly design).
Figure 6.1 List of ASP.NET Web Forms
File Name | Purpose | Links To |
Login.aspx | Allow user to login | addressbooklist.aspx |
addressbooklist.aspx | View list of a user’s address books | createbook.aspx |
|
| listusers.aspx |
createbook.aspx | Create a new address book | addressbooklist.aspx |
listusers.aspx | List users within an address book | createbook.aspx |
|
| createuser.aspx |
createuser.aspx | Create a new user within an address book | listusers.aspx |
Take time now to review each file and the code behind each. First look at the login.aspx page that allows the user to log in and get their UUID, which gives them access to the rest of the application. Also, you may wish to start adding some functionality to the application. One important issue would be a way to initially create a user when no address books are defined. Personally I would create an application administrator (you), and create a global address book. And then each new user who is created (first time in) will be added to this global address book. And then each of these users can create/edit their own address books, etc... Take the logic from the createuser.aspx page and create your own, generic page to allow for this functionality. You could also consider adding in a feature to share contacts between address books. All you would really need is another table to represent the intersection between the shared contacts and the appropriate users.
You can test this application by hitting the Start button in the Integrated Development Environment (IDE) or by going to "Debug", "Start" menu items.
Section 7: The XML Web Services Presentation Interface
By simply exposing the methods in our Business tier within the "AddressBookService" application, we can easily create a new interface into our application based on XML Web Services (or any other way, like Windows Forms, etc...). I have started this interface for you, but left it incomplete on purpose, to allow you to get your hands dirty by trying to port the rest of the Business tier to this new interface. All you really need to know is that each user will start by logging into the application and getting their UUID. Then each subsequent request will also pass this UUID in with the each method call. An alternative to this would be to use SOAP headers so that you do not need to expose the methods with the additional UUID string on each method.
Conclusion
During your examination of this article and the supplied code, you must always keep in mind what it was intended for -- a simple demonstration on how one would develop an N-tier application. You should take into consideration the concepts, more than the simple language or my choice of development platform/framework and environment. You can easily take and apply these concepts back to your ASP/COM or JSP/Bean environments; it really doesn't matter, just as long as you understand the usefulness of keeping things separate using this tiered approach.
Some more things that I do recommend that you look into include:
1. Refactoring (Extreme Programming -XP)
- http://www.aw.com/cseng/titles/0-201-89542-0/techniques/refactoring.htm
- http://www.aw.com/cseng/titles/0-201-89542-0/vidrefact/vidrefact.html
- http://www.industriallogic.com/xp/refactoring/
2. Object -Orientated Design Patterns
3. Systems Development Life Cycle
- http://www.dbm.state.md.us/mdplan/apdx-a.htm
- http://searchvb.techtarget.com/sDefinition/0,,sid8_gci755068,00.html
- http://www.student.richmond.edu/~mbarkley/portfolio/projects/SDLC%20Lecture(1).ppt
4. Other
I did my best to produce code, which is in good working order, but as with most applications, there will always be bugs. If you do find any problems, please send me an email and I'll try to make any fixes that people send in. Also, if you do take the time to create a Data Access tier for any other DBMS than Access, or maybe you finish the ASP.NET or Web Services interfaces, send me the code, and I'll add it to the library (giving you full credits of course!). If you do plan on completing any of this and you need help, drop me a line, and Ill be glad to lend a hand.
I do have to admit that this is my first exposure to using VS.NET for any type of application. I have spent a lot of time with the .NET Framework and C#, but, specifically with this tool, this application was my first! Usually I take what Microsoft says with a grain of salt. But when they say that the .NET Framework and VS.NET increase productivity, they are very right. I believe I will finally make the switch out of simple Notepad (or IDM Computer Solution's UltraEdit) and into this development environment.
This article is intended for all levels of developers, and I hope you find it useful.
About the Author
Robert Chartier has worked in the information technologies field for more than 7 years. While studying at college he began his career working as a software and hardware technician at the college, supporting a user base of thousands of students and hundreds of instructors. Once his college days were finished he moved on to full-time studies at a university in the lower mainland of British Columbia, and landed a full-time job developing large projects for distribution on many platforms, mediums, and languages.
His next position enabled him to tap into the Internet development market on a larger and more focused scale. In his spare time he began writing and producing content for developer-specific sites focusing on Microsoft technologies (ASP, COM/COM+, etc.). He has also been a part of many open forums on cutting-edge technologies, such as the .NET Framework and Web Services (SOAP), and has been invited to speak at large developer conferences and contribute to many technical publications.
His next step was to take a position with a large B2B training marketplace, where he developed many tools, including a very comprehensive search engine with custom business rules for weighting, sorting, and analysis (COM+). This led him into strong development with beta versions of Commerce Server 2000 and BizTalk Server 2000. His next opportunity included a large Internet development effort using technologies such as JSP (Java Beans, J2EE), Oracle, WebLogic, etc. His current position as vice president of technology for Santra Technology (http://www.santra.com) has allowed him to focus more time on the Web Services market space. Santra is an award-winning, industry leader in this cutting-edge technology, focusing on Web Service monitoring, alerting, and performance measurement.
Robert Chartier can be reached at rob@aspfree.com.