Adding the Business Objects


Sams Teach Yourself ASP.NET in 21 Days, Second Edition
By Chris Payne
Table of Contents
Week 3.  In Review

Recall from Day 15, "Using Business Objects," that business objects often represent a real-world object; they contain properties and methods to completely represent that object. For example, a business object that represents a car would contain properties such as color, make, and model, and methods such as start, brake, and open door.

In the banking application, a customer's account is easily represented in this manner. Your business object will contain methods to retrieve and update a user's account, and perform other general functions.

Luckily, you've already written all the code that will go into your business object; it is interspersed throughout your ASP.NET pages. All you need to do is collect the code you have already written and place it in the appropriate methods of the business object. After you've compiled the business object, your ASP.NET page will require a slight modification to take advantage of it. Listing BP3.1 shows the entire VB.NET source file for your account object.

Listing BP3.1 Representing an Account with a Business Object
 1:  Imports System 2:  Imports System.Data 3:  Imports System.Data.OleDb 4: 5:  Namespace ASPNETBank 6: 7:     Public Class Account 8:        'declare connection object 9:        private objConn as new OleDbConnection("Provider=" & _ 10:           "Microsoft.Jet.OLEDB.4.0;" & _ 11:           "Data Source=c:\ASPNET\data\banking.mdb") 12:        private strUsername as string 13: 14:        public sub New(Username as string) 15:           strUsername = Username 16:        end sub 17: 18:        '**************************************************** 19:        ' This function returns the balance of the account 20:        ' with the specified user ID 21:        '**************************************************** 22:        public function GetBalance() as Decimal 23:           dim decBalance as decimal 24:           dim objCmd as new OleDbCommand( _ 25:              "spRetrieveBalance", objConn) 26:           objCmd.CommandType = CommandType.StoredProcedure 27:           dim objReader as OleDbDataReader 28: 29:           'set parameters for stored procedure 30:           dim objParam as OleDbParameter 31:           objParam = objCmd.Parameters.Add("@UserID", _ 32:              OleDbType.BSTR) 33:           objParam.Direction = ParameterDirection.Input 34:           objParam.Value = strUsername 35: 36:           try 37:              objConn.Open() 38:              decBalance = CType(objCmd.ExecuteScalar, _ 39:                 Decimal) 40:              objConn.Close 41:           catch ex as OleDbException 42:              throw ex 43:           end try 44: 45:           return decBalance 46:        end function 47: 48:        '**************************************************** 49:        ' Returns all transactions for a given user id 50:        '**************************************************** 51:        public function GetTransactions() as OleDbDataReader 52:           dim objCmd as new OleDbCommand( _ 53:              "spGetTransactions", objConn) 54:           objCmd.CommandType = CommandType.StoredProcedure 55:           dim objReader as OleDbDataReader 56: 57:           'set parameters for stored procedure 58:           dim objParam as OleDbParameter 59:           objParam = objCmd.Parameters.Add("@UserID", _ 60:              OleDbType.BSTR) 61:           objParam.Direction = ParameterDirection.Input 62:           objParam.Value = strUsername 63: 64:           try 65:              objConn.Open() 66:              return objCmd.ExecuteReader 67:           catch ex as OleDbException 68:              throw ex 69:           end try 70:        end function 71: 72:        '**************************************************** 73:        ' Adds a transaction into the database, calling 74:        ' spInsertTransaction and specifying amount, payee, 75:        ' and user id 76:        '**************************************************** 77:        public sub AddTransaction(strPayee as string, decAmount as Decimal) 78:           dim objCmd as OleDbCommand = new OleDbCommand _ 79:              ("spInsertTransaction", objConn) 80:           objCmd.CommandType = CommandType.StoredProcedure 81: 82:           'set parameters for stored procedure 83:           dim objParam as OleDbParameter 84:           objParam = objCmd.Parameters.Add("@Date", _ 85:              OleDbType.Date) 86:           objParam.Direction = ParameterDirection.Input 87:           objParam.Value = Datetime.Now 88: 89:           objParam = objCmd.Parameters.Add("@Amount", _ 90:              OleDbType.Decimal) 91:           objParam.Direction = ParameterDirection.Input 92:           objParam.Value = decAmount 93: 94:           objParam = objCmd.Parameters.Add("@Payee", _ 95:              OleDbType.BSTR) 96:           objParam.Direction = ParameterDirection.Input 97:           objParam.Value = strPayee 98: 99:           objParam = objCmd.Parameters.Add("@UserID", _ 100:              OleDbType.BSTR) 101:           objParam.Direction = ParameterDirection.Input 102:           objParam.Value = strUsername 103: 104:           try 105:              objConn.Open() 106:              objCmd.ExecuteNonQuery 107:              objConn.Close 108:           catch ex as OleDbException 109:              throw ex 110:           end try 111:        end sub 112: 113:        '**************************************************** 114:        ' Updates the account balance 115:        ' calls spUpdateBalance 116:        '**************************************************** 117:        public sub UpdateBalance(decNewAmount as Decimal) 118:           dim objCmd as OleDbCommand = new OleDbCommand _ 119:              ("spUpdateBalance", objConn) 120:           objCmd.CommandType = CommandType.StoredProcedure 121: 122:           'set parameters for stored procedure 123:           dim objParam as OleDbParameter 124:           objParam = objCmd.Parameters.Add("@NewBalance", _ 125:              OleDbType.Decimal) 126:           objParam.Direction = ParameterDirection.Input 127:           objParam.Value = decNewAmount 128: 129:           objParam = objCmd.Parameters.Add("@UserID", _ 130:              OleDbType.BSTR) 131:           objParam.Direction = ParameterDirection.Input 132:           objParam.Value = strUsername 133: 134:           try 135:              objConn.Open() 136:              objCmd.ExecuteNonQuery 137:              objConn.Close 138:           catch ex as OleDbException 139:              throw ex 140:           end try 141:        end sub 142:     End Class 143:  End Namespace 


Save this file as Account.vb. Much of this code should look familiar. The GetBalance function on line 22 was pulled from the account.aspx and bills.aspx files; the GetTransactions function (line 51) was pulled from account.aspx; both AddTransaction on line 77 and UpdateBalance on line 117 were pulled from bills.aspx. Much of the code has remained the same since the last time you looked at these methods, so I won't go into detail here (see "Week 2 in Review" for details on each method). However, there are some vital changes that you should know about.

On line 9, you declare an OleDbConnection object for use with your methods; it's easier to create it once here than it is to create it in every single method. Line 12 creates a private variable to hold a user's account name; you'll return to this in a moment.

Line 14 declares the New method. This method is a constructor for the Account class; it executes whenever you instantiate the class (recall that in C#, the constructor shares the same name as the class Account, in this case). For example, the New method is executed when you use the following code:

 dim objAccount as New Account 

or in C#:

 Account objAccount = new Account() 

This method takes a string parameter, Username, and stores it in the private strUsername variable you created on line 12. Now users of this class can use the following code to instantiate this class:

 dim objAccount as New Account("clpayne") 

This value will be used to retrieve the correct account from the database it will be supplied from the authentication cookie created when the user logs on (more on this later).


Because you've created a constructor that takes a parameter, your user must supply a value for that parameter whenever the class is instantiated. The following line will now generate an error:

 dim objAccount as New Account 

If you want users to still be able to use the preceding code, create another New method that doesn't accept any parameters and add the Overloads keyword to both methods:

 sub Overloads New Account(Username as String) ... sub Overloads New Account() ... 

This creates an overloaded method. Recall that overloaded methods are methods that have the same name, but take different parameters (and possibly execute different code). Thus, overloaded methods make it possible for your class to be instantiated in multiple ways. See Day 15 for more information, including how to do this in C#.

Next, the first two methods have been changed from a sub to a function. The original methods didn't need to return any values; they assigned any calculated values to labels or text boxes. However, the object can't do this. So, it instead returns the calculated data to the calling page, which will then assign it to the proper display element. Notice that each function also returns an appropriate type. For example, beginning on line 22, the GetBalance function returns a Decimal:

 public function GetBalance() as Decimal    dim decBalance as decimal    ...    return decBalance end function 

Likewise, GetTransactions returns an OleDbDataReader.

Each of the methods in Listing BP3.1 uses OleDbParameters to retrieve data from the database, one of which is the @UserID parameter, which ensures that you are retrieving the correct account information.

The code uses the value from the strUsername variable that is created on line 12, and instantiated on line 15, in the class's constructor. This variable will contain the account name supplied from the code that instantiates this class.

Now, compile this object for use in your pages. From the command prompt, in the same directory that this listing was saved in, issue the following command:

 vbc /t:library /out:..\..\bin\ASPNETBank.dll /r:System.dll / Account.vb 

With that done, it's time to examine that changes to each of the ASP.NET pages. None of the UI has changed, so this discussion looks only at the code declaration blocks. Listing BP3.2 shows the changes to account.aspx.

Listing BP3.2 Implementing the Account Object in account.aspx
 1:  <script runat="server"> 2:     sub Page_Load(Sender as Object, e as EventArgs) 3:        dim objAccount as New ASPNETBank.Account( _ 4:           User.Identity.Name) 5:        lblBalance.Text = "<b>$" & objAccount.GetBalance() & _ 6:           "</b>" 7:        dgTransactions.DataSource = objAccount.GetTransactions 8:        DataBind 9:     end sub 10:  </script> 


Quite a change from last time! On line 3, you instantiate your newly created Account object, supplying the user's account name. (The User object contains information about the authenticated user; Identity.Name specifies the value stored in the authentication cookie. This means that this page won't work unless you have some form of authentication enabled we'll create a web.config file to do so in a moment.) On line 5, you use the GetBalance function to retrieve a Decimal variable that contains the account balance, and display it in a label named lblBalance (not shown here).

Next, on line 7, the GetTransactions method returns an OleDbDataReader object which you bind to a DataGrid named dgTransactions (again, not shown here). Call the DataBind method on line 8, and that's it! Viewing this page from the browser should produce the same image as last time, shown in Figure BP3.1.

Figure BP3.1. Viewing the account information with a new Account object.


Let's look at the changes for bills.aspx, shown in Listing BP3.3.

Listing BP3.3 Implementing the Account Object in bills.aspx
 1:  <script runat="server"> 2:     sub PayBill(Sender as Object, e as EventArgs) 3:        dim objAccount as new ASPNETBank.Account( _ 4:           User.Identity.Name) 5:        dim decBalance as Decimal = objAccount.GetBalance() 6:        dim decAmount as Decimal = tbAmount.Text 7: 8:        if decAmount < 0 then 9:           lblMessage.Text = "<font color=red>The " & _ 10:              "transaction amount cannot be negative!" & _ 11:              "</font>" 12:           exit sub 13:        end if 14: 15:        if decAmount <= decBalance then 16:           objAccount.UpdateBalance(decBalance - decAmount) 17:           objAccount.AddTransaction(tbPayee.Text, decAmount) 18: 19:           lblMessage.Text = "<font color=red>" & _ 20:              "Transaction added.</font>" 21:           tbAmount.Text = "" 22:           tbPayee.Text = "" 23:        else 24:           lblMessage.Text = "<font color=red>You do not " & _ 25:              "have enough funds to complete this " & _ 26:              "transaction!</font>" 27:        end if 28:     end sub 29:  </script> 


This page contains only one method, PayBill, which is the event handler for a submit button click. Essentially, this page compares the current balance of the account to the value specified by the user (to pay a bill). If the former is greater than the latter, the transaction is added to the database, and the value is subtracted from the account. Otherwise, the user is alerted of the error.

On line 3, you create a new Account object just as you did for Listing BP3.2. Again, because we haven't yet implemented authentication, this page won't work. Line 5 retrieves the balance of the account, and line 6 retrieves the value specified by the user. Line 8 simply ensures that the amount specified by the user isn't negative, and alerts the user if it is. Line 15 performs the check to ensure that the current balance is greater than the bill amount. Lines 16 and 17 are responsible for calling methods in the Account object that subtract the value from the account and add the transaction to the database, respectively. Finally, a message is displayed to the user on lines 19 22. This page is shown in Figure BP3.2.

Figure BP3.2. The updated bills.aspx page.


login.aspx changes only slightly. Because you now know how to use forms authentication, you can take advantage of it to log in the users properly. Previously, all you did was set a cookie and redirect the user. Now, you can set a valid authentication cookie. In login.aspx, change the following line (line 48 of Listing BP2.6):

 Response.Cookies("Account").Value = intID 

to read as follows:

 FormsAuthentication.SetAuthCookie(intID, false) 

That's all there is to it! Additionally, because you now log users in properly, you'll want to allow them to log out as well. Listing BP3.4 shows logout.aspx, which removes the authentication cookie.

Listing BP3.4 Logging Users Out Is a Simple Process
 1:  <%@ Page Language="VB" %> 2:  <%@ Register TagPrefix="ASPNETBank" TagName="Header" src="/books/4/226/1/html/2/header.ascx" %> 3: 4:  <script runat="server"> 5: 6:     '******************************************************* 7:     ' 8:     ' Logout.aspx: Logs users out 9:     ' 10:     '******************************************************* 11: 12:     '******************************************************* 13:     ' We need to log users out as soon as they hit this page 14:     ' so use Page_Load and CookieAuthentication.Signout 15:     '******************************************************* 16:     sub Page_Load(Sender as Object, e as EventArgs) 17:        FormsAuthentication.SignOut 18:     end sub 19:  </script> 20: 21:  <html><body topmargin="0" leftmargin="0"> 22:     <ASPNETBank:Header runat="server" /> 23:     <font face="arial"> 24:     <p> 25:     Thank you for using the ASP.NET Banking Center. Please 26:     come again!.<p> 27: 28:     <a href="login.aspx">Login again?</a><p> 29:     </font> 30:  </body></html> 

As you can see, the only code in this page is in the Page_Load method on line 16. FormsAuthentication.SignOut removes the authentication cookie you set when the user logged in, which effectively logs the user out. If she wants to access your application again, she must log in again.

You also know how to implement security in your application through web.config. You'll need to protect the pages in this application so that unauthorized users aren't able to see account information. Specifically, you'll have to secure account.aspx and bills.aspx. Listing BP3.5 shows the web.config file that implements these changes.

Listing BP3.5 Implementing Security with web.config
 1:  <configuration> 2:     <system.web> 3:        <authentication mode="Forms"> 4:           <forms name="AuthCookie" loginUrl="tyaspnet21days/bp3/login.aspx"/> 5:        </authentication> 6:     </system.web> 7:     <location path="tyaspnet21days/BP3/account.aspx"> 8:        <system.web> 9:           <authorization> 10:                 <deny users="?"/> 11:           </authorization> 12:        </system.web> 13:     </location> 14:     <location path="tyaspnet21days/BP3/bills.aspx"> 15:        <system.web> 16:           <authorization> 17:              <deny users="?"/> 18:           </authorization> 19:        </system.web> 20:     </location> 21:  </configuration> 

After your lesson in security in Day 21, this listing should be easy to understand. Line 3 turns on forms authentication. Line 4 provides the name of the authentication cookie and the URL to which unauthenticated users should be directed, login.aspx. The <location> elements on lines 7 and 14 use the <authorization> tags to deny access to account.aspx and bills.aspx to anonymous users. Note that this web.config must reside in the root directory of your application. The <location> tags throw an error when used in subdirectories.

The files header.ascx and nav.ascx stay the same. These two were static user controls, and didn't contain any code to modify.

You might be wondering why you haven't created a User object to represent the current user and log him in, sign him out, and so on. Currently, the only method that applies to users is the submit event handler for login.aspx, which validates credentials against the database. Because there's only one method here and it won't be used anywhere else, there's no need to spend the energy to move it into a business object. (Don't let that stop you, however, if you feel the urge to create more business objects!)


    Sams Teach Yourself ASP. NET in 21 Days
    Sams Teach Yourself ASP.NET in 21 Days (2nd Edition)
    ISBN: 0672324458
    EAN: 2147483647
    Year: 2003
    Pages: 307
    Authors: Chris Payne © 2008-2017.
    If you may any questions please contact us: