Writing Multitier Applications in ASP.NET...
You can go well beyond codebehind to separate presentation, business rules, and data handling in your ASP.NET applications.
Often developers think of an .aspx page and a codebehind page as separation of code and content, and it is, up to a point. We can go further though. This article presents a small application where we use an .aspx page, a codebehind page, a business rules class, and a data layer class. This separates presentation from code, but also separates code into logical segments.
The codebehind page will call the business rules class (BusObject.dll) to enforce business rules. The business rules class will enforce business rules and, if the input passes the rules, calls the data class (DataObject.dll) to do an insert into a table of data of the information collected from the presentation layer. This involves writing two VB class files, BusObject.vb and DataObject.vb and then compiling them into dll's.
To save space I will not show the .aspx page (it is included in the downloadable code). Suffice it to say that the page presents a typical form collecting FirstName, LastName, Address1, Address2, City, State, and ZipCode. It also includes some required validators, a submit button, and a label control to display error messages. (State should really be a DropDownList instead of a TextBox, but I didn't have a state table at my disposal.)
Let's get right to the codebehind (GetInfo.aspx.vb). As you can see from the code below all the codebehind page is really doing is calling the CheckInput method of our business rules object (BusObject.dll). We dim objBus as a new BusObject, then pass to it the data collected on the .aspx page.
|
Public Class GetInfo Inherits System.Web.UI.Page '(Web Form Designer Generated Code Omitted) Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'Put user code to initialize the page here End Sub Protected Sub btnSubmit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSubmit.Click Dim objBus As New BusObject LblErrMsg.Text = "" If IsValid Then Try objBus.CheckInput(txtFirstName.Text, _ txtLastName.Text, _ txtAddr1.Text, _ txtAddr2.Text, _ txtCity.Text, _ txtState.Text, _ txtZipCode.Text) Catch ex As Exception lblErrMsg.Text = ex.Message.ToString() End Try End If End Sub End Class |
Next comes our business rules class (BusObject.vb). The code for it is shown below. You create a vb class file and then compile it. Before you compile it, however, you must first compile the data object (DataObject.vb). It is necessary to compile DataObject.vb first because BusObject.vb contains a reference to DataObject. You will receive an error if you try to compile BusObject first since the compiler won't be able to find DataObject.
Here you can see that we created the sub routine (method) CheckInput that we called from the codebehind page. Obviously the business rules (FirstName can't be 'test' and New Yorkers can't particpate) are not 'real world' but hopefully they get the point across that you can create business rules and throw an exception if they are violated. If the data gets by the business rules without throwing an exception the program then calls the TableInsert method of the DataObject and passes the collected data to it.
|
Imports System Namespace DotNetJohn Public Class BusObject Sub CheckInput(ByVal firstname As String, _ ByVal lastname As String, _ ByVal address1 As String, _ ByVal address2 As String, _ ByVal city As String, _ ByVal state As String, _ ByVal zipcode As String) If firstname = "test" Then Throw New ArgumentException("Test is not allowed as a first name!") End If If state.ToUpper() = "NEW YORK" Or state.ToUpper() = "NY" Then Throw New ArgumentException("New Yorkers can't participate!") End If Dim objData As New DataObject objData.TableInsert(firstname, lastname, address1, address2, city, state, zipcode) End Sub End Class End Namespace |
Finally comes our data handling class DataObject.vb. It has one method (TableInsert) which accepts the data elements passed in by BusObject, establishes a connection to the database, and writes the information to the table. The code is a little longer than it might be because we have used parameters to pass the data to the insert statement. Otherwise it is a pretty straight forward piece of code.
In both DataObject and BusObject if an exception occurs we throw it and the label control on the .aspx page displays the error message.
|
Imports System.Data Imports System.Data.SqlClient Imports System.Configuration Namespace DotNetJohn Public Class DataObject Public Sub TableInsert(ByVal firstname As String, _ ByVal lastname As String, _ ByVal address1 As String, _ ByVal address2 As String, _ ByVal city As String, _ ByVal state As String, _ ByVal zipcode As String) Dim objCmd As SqlCommand Dim objConn As SqlConnection Dim strSQL As String = "Insert into myTable (" _ & "firstname, lastName, address1, address2, " _ & "City, State, zipcode " _ & ") Values " _ & "(@Firstname, @LastName, @Address1, @Address2, " _ & "@City, @State, @ZipCode)" Try objConn = New SqlConnection(ConfigurationSettings.AppSettings("ConnectionString")) objConn.Open() objCmd = New SqlCommand(strSQL, objConn) With objCmd.Parameters .Add(New SqlParameter("@Firstname", firstname)) .Add(New SqlParameter("@LastName", lastname)) .Add(New SqlParameter("@Address1", address1)) .Add(New SqlParameter("@Address2", address2)) .Add(New SqlParameter("@City", city)) .Add(New SqlParameter("@State", state)) .Add(New SqlParameter("@ZipCode", zipcode)) End With objCmd.ExecuteNonQuery() Catch ex As Exception Throw New ArgumentException(ex.Message.ToString()) Finally objConn.Dispose() End Try End Sub End Class End Namespace |
DataObject.vb can be compiled from the command prompt by typing:
vbc /t:library DataObject.vb
BusObject.vb can be compiled from the command prompt by typing:
vbc /t:library /r:DataObject.dll BusObject.vb
I hope this small application demonstrates how to really separate your code into logical segments. Doing this should make maintenance of the code a little easier because if the business rules change or the database changes you only have a fairly small, self contained code segment to modify.
You may download the code here.