Implementation of a 3 – Tier Web Application
for Mobile Devices using Microsoft .NET platform
Rahil Kidwai
Department of Computer Science
Wichita State University
CS898T –Mobile & Wireless Networks
Dr. Chin-Chih Chang
Table of Contents
1.0Introduction
2.0Application Overview
2.1StockTrade - an MMIT Application
2.2Application Architecture
2.2.1The Data Layer
2.2.2Application Layer
2.2.3Presentation Layer
2.3Technologies Used
2.3.1Microsoft .NET Framework
2.3.2C# (CSharp)
2.3.3ASP.NET
2.3.4SQLServer 2000 DBMS
3.0Implementation
3.1Implementation of Data Layer
3.1.1Database Schema
3.1.2Stored Procedures
3.1.3‘dlStockTrade’ Class
3.2Implementation of Business Logic Layer
3.2.1Class ‘Order’
3.2.2Class ‘Portfolio’
3.2.3Class ‘Ticker’
3.2.4Class ‘blStockTrade’
3.3Presentation Layer (of website for normal users)
3.3.1Login web page (code behind file)
3.3.2logout web page (code behind file)
3.3.3Main web page (code behind file)
3.3.4Portfolio web page (code behind file)
3.3.5Search web page (code behind file)
3.3.6Buysell web page (code behind file)
3.3.7‘Menu’ user control (code behind file)
3.4Presentation Layer Implementation (for mobile devices)
3.4.1‘Login’ web Page
3.4.2‘Main’ web Page
3.4.3‘Search’ web Page
3.4.4‘Buysell’ web Page
3.4.5Portfolio web Page
4.0References
List of Figures
Figure 1 3 – Tier Application Architecture………………………………………… 3
Figure 2 Schema of the database ……………………………………………………..6
1.0Introduction
Over the past few years, the world has seen an explosion of new wireless devices, such as cell phones, pagers, and personal digital assistants (PDAs), which enable users to browse Web sites at any time from any location. Developing web applications for these devices is challenging for the following reasons:
- Different markup languages are necessary, including HTML for PDAs, wireless markup language (WML) for wireless application protocol (WAP) cell phones, and compact HTML (cHTML) for Japanese i-mode phones.
- Devices have different form factors. For example, devices have varying numbers of display lines, horizontal or vertical screen orientation, and color or black and white displays.
- Devices have different network connectivity, ranging from 9.6 KB cellular connections to 11 MB Wireless LANs.
- Devices have different capabilities. Some devices can display images, some can make phone calls, and some can receive notification messages.
The Microsoft Mobile Internet Toolkit addresses these challenges by isolating them from the details of wireless development. Thus, developers can quickly and easily build a single, mobile Web application that delivers appropriate markup for a wide variety of mobile devices.
It has been very interesting and challenging project. I want to thank Dr. Chang for his support for the completion of my project.
2.0Application Overview
2.1StockTrade - an MMIT Application
This project is a real world application, a web site which can be efficiently accessed though mobile devices as well. Using this web site people will be able to monitor and trade stocks from any where any time using their mobile devices provided their devices have access to the internet.
StockTrade is a web application through which its users can:
- Login to their accounts,
- Trade stocks,
- View their portfolio,
- Search for specific information, and
- View financial news.
2.2Application Architecture
This web application is a 3-tier application. A 3-tier application is an application program that is organized into three major parts or layers, each of which is distributed to a different place or places in a network. The three parts or layers are:
- Client Layer or Presentation Layer
- Application Layer
- Data Layer or Database Layer
Figure 1 : 3 – Tier Application Architecture
2.2.1The Data Layer
The data layer consists of two separate layers. The first consists of the set of stored procedures implemented directly within the database. These stored procedures run on the server and provide only basic data. Using stored procedures instead of embedding queries directly in the web pages greatly improves performance as they are pre-compiled, pre-optimized and separately tested.
The next layer consists of a set of classes which calls and handle the stored procedures. These classes handle all requests to or from the actual database and provide a shield to the application data ensuring data integrity. Also this provides the only way to modify data and no other source can modify data in the database in any way.
2.2.2Application Layer
This layer is implemented in order to encapsulate business rules. Here I have implemented some classes to encapsulate the business functionality. They neither access data (except through the data layer) nor do they bother with the display or presentation of this data to the user. They only deal with the complexities of the business itself.
2.2.3Presentation Layer
This layer handles everything to do with the presentation of the system and includes all the web pages of this application. This layer only interacts with the business layer.
The advantages of building application using 3-Tier Architecture are:
-Easy maintenance
-Simplifies future enhancements
-Code reuse
I have developed two versions of this application, one is for users connecting through their desktop PCs or laptop systems and the other is for users connecting through their mobile devices. The main advantage is that I just have to change the presentation layer of my application to allow for mobile devices. Both applications are using the same data and application layer code.
2.3Technologies Used
2.3.1Microsoft .NET Framework
.NET (dot-net) is the name Microsoft gives to its general vision of the future of computing, the view being of a world in which many applications run in a distributed manner across the Internet. We can identify a number of different motivations driving this vision.
Distributed computing is rather like object oriented programming, in that it encourages specialized code to be collected in one place, rather than copied redundantly in lots of places. There are thus potential efficiency gains to be made in moving to the distributed model.
By collecting specialized code in one place and opening up a generally accessible interface to it, different types of machines (phones, handhelds, desktops, etc.) can all be supported with the same code. Hence Microsoft's 'run-anywhere' aspiration.
By controlling real-time access to some of the distributed nodes (especially those concerning authentication) companies like Microsoft can control more easily the running of its applications. It moves applications further into the area of 'services provided' rather than 'objects owned'.
Since Microsoft sees its future as providing software services in distributed applications, the .NET framework has been written so that applications on other platforms will be able to access these services. For example, .NET has been built upon open standard technologies like XML and SOAP.
At the development end of the .NET vision is the .NET Framework. This contains the Common Language Runtime, the .NET Framework Classes, and higher-level features like ASP.NET and WinForms.
The Common Language Runtime (CLR) manages the execution of code compiled for the .NET platform. The CLR has two interesting features. Firstly, its specification has been opened up so that it can be ported to non-Windows platforms. Secondly, any number of different languages can be used to manipulate the .NET framework classes, and the CLR will support them.
2.3.2C# (CSharp)
Not all of the supported languages fit entirely neatly into the .NET framework, but one language that is guaranteed to fit in perfectly is C#. This new language, a successor to C++, has been released in conjunction with the .NET framework, and is likely to be the language of choice for many developers working on .NET applications.
2.3.3ASP.NET
ASP.NET is a programming framework built on the common language runtime that can be used on a server to build powerful Web applications. ASP.NET is compiled common language runtime code running on the server. ASP.NET take advantage of early binding, just-in-time compilation, native optimization, and caching services right out of the box.
The ASP.NET framework is complemented by a rich toolbox and designer in the Visual Studio IDE. WYSIWYG editing, drag-and-drop server controls, and automatic deployment are some features this powerful tool provides.
Because ASP.NET is based on the common language runtime, the power and flexibility of that entire platform is available to Web application developers. Further, common language runtime interoperability guarantees that your existing investment in COM-based development is preserved when migrating to ASP.NET.
ASP.NET makes it easy to perform common tasks, from simple form submission and client authentication to deployment and site configuration. Additionally, the common language runtime simplifies development, with managed code services such as automatic reference counting and garbage collection.
2.3.4SQLServer 2000 DBMS
SQL Server™ 2000 has been used as the DBMS for this application.SQL Server™ 2000 is a powerful Database Management System by Microsoft.
3.0Implementation
3.1Implementation of Data Layer
3.1.1Database Schema
Following is the schema of the database:
Figure 2 : Schema of the database
Following are the main points of this schema:
- There can be several orders of an account, but each order belongs to only one account.
- Each account can have several portfolios.
- Each portfolio belongs to a particular Ticker.
3.1.2Stored Procedures
3.1.2.1STCheckFunds
This procedure determines if there are enough funds available to place a specific order.
CREATE PROCEDURE [STCheckFunds]
(@account int, @amount float)
AS
DECLARE
@availablefloat,@retValuebit
BEGIN
SELECT @available = AccountBalance FROM STAccounts
WHERE AccountId = @account
IF @available < @amount
SET @retValue = 0
ELSE
SET @retValue = 1
RETURN @retValue
END
3.1.2.2STCheckStocks
This procedure determines if the quantity entered against a sell order is valid or not.
CREATE PROCEDURE [STCheckStocks]
(@account int, @symbol varchar(50), @quantity int)
AS
DECLARE
@tid int,@totalint,@count int,@retValueint
BEGIN
SELECT @count = COUNT(*) FROM STTickers WHERE Symbol = @symbol
IF @count = 0
SET @retValue = 0
ELSE
BEGIN
SELECT @tid = TickerId FROM STTickers WHERE Symbol =
@symbol
SELECT @total = SUM(Quantity) FROM STPortfolioS WHERE
AccountId= @account AND TickerId = @tid
IF @total >= @quantity
SET @retValue = 1
ELSE
SET @retValue = 0
END
RETURN @retValue
END
3.1.2.3STPlaceOrder
This procedure enters a new order into the database.
CREATE PROCEDURE [STPlaceOrder]
(@account int, @symbol varchar(50), @buysell bit, @quantity int, @price float)
AS
DECLARE
@value int,@count int,@tidint
BEGIN
SELECT @count = COUNT(*) FROM STTickers WHERE Symbol = @symbol
IF @count = 1
BEGIN
SELECT @tid = TickerId FROM STTickers WHERE Symbol= @symbol
INSERT INTO STOrders (AccountId, TickerId, BuySell,
Quantity, PricePlaced) VALUES (@account, @tid, @buysell, @quantity, @price)
SET @value = @@Identity
END
ELSE
SET @value = -1
RETURN @value
END
3.1.2.4STPortfolio
This procedure returns all the portfolios of a given account.
CREATE PROCEDURE [STPortfolio]
(@accountId int)
AS
BEGIN
SELECT T.Name, T.Symbol, P.Quantity, T.LastPrice
FROM STPortfolios P, STTickers T
WHERE T.TickerId = P.TickerId AND P.AccountId= @accountId
END
3.1.2.5STTickerDetails
This procedure returns the details of a particular Ticker symbol.
CREATE PROCEDURE [STTickerDetails]
(@ticker varchar(100))
AS
BEGIN
SELECT TickerId, Symbol, Name, LastPrice
FROM STTickers
WHERE Symbol = @ticker
END
3.1.2.6STVerifyLogin
This procedure is used to verify the given login information.
CREATE PROCEDURE [STVerifyLogin]
(@username varchar(50), @password varchar(50))
AS
DECLARE
@valid int,@count int
BEGIN
SELECT @count = COUNT(*) FROM STAccounts WHERE login = @username AND password = @password
IF @count = 1
SELECT @valid = AccountId FROM STAccounts WHERE login =
@username AND password = @password
ELSE
SET @valid = 0
RETURN @valid
END
3.1.3‘dlStockTrade’ Class
Below is the code of the class used to implement the data layer.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
namespace StockTrade.Components.DLL
{
publicclass dlStockTrade
{
privateconststring strConnection = "Server=newton;UID=rpuser;PWD=rpuser;
database=ResourceScheduler;";
// default constructor
private dlStockTrade() { }
//************************************************
// Returns '0' for invalid login information
// otherwise returns AccountId of the account
//************************************************
publicstaticint verifyLogin(string user, string pwd)
{
SqlConnection connection = getConnection();
SqlCommand command = new SqlCommand("STVerifyLogin",
connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@username",user);
command.Parameters.Add("@password", pwd);
SqlParameter retValue = command.Parameters.Add(
"ReturnValue",SqlDbType.Int);
retValue.Direction = ParameterDirection.ReturnValue;
connection.Open();
command.ExecuteNonQuery();
int result = Convert.ToInt32(
command.Parameters["ReturnValue"].Value);
connection.Close();
return result;
}
//************************************************
// Retrieves whole portfolio of a particular account
//************************************************
publicstatic DataSet getPortfolio (int accountId)
{
SqlConnection connection = getConnection();
SqlCommand command = new SqlCommand(
"STPortfolio", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@accountId",accountId);
SqlDataAdapter da = new SqlDataAdapter(command);
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}
//************************************************
// Retrieves details of a ticker symbol
//************************************************
publicstatic DataSet getTickerDetails(string symbol)
{
SqlConnection connection = getConnection();
SqlCommand command = new SqlCommand(
"STTickerDetails", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@ticker",symbol);
SqlDataAdapter da = new SqlDataAdapter(command);
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}
//************************************************
// Places a Order
// returns orderId, -1 for invalid ticker,
// 0 for other invalid data
//************************************************
publicstaticint PlaceOrder (int acct, string sym,
bool bs, int qty, double placed)
{
SqlConnection connection = getConnection();
SqlCommand command = new SqlCommand(
"STPlaceOrder", connection);
command.CommandType = CommandType.StoredProcedure;
byte b = bs ? (byte)1 : (byte)0;
command.Parameters.Add("@account",acct);
command.Parameters.Add("@symbol",sym);
command.Parameters.Add("@buysell",b);
command.Parameters.Add("@quantity",qty);
command.Parameters.Add("@price",placed);
SqlParameter retValue = command.Parameters.Add(
"ReturnValue",SqlDbType.Int);
retValue.Direction = ParameterDirection.ReturnValue;
connection.Open();
command.ExecuteNonQuery();
int result = Convert.ToInt32(
command.Parameters["ReturnValue"].Value);
connection.Close();
return result;
}
//************************************************
// Checks for funds before placing a Order
// returns 1 if sufficient funds are available
// to order else 0
//************************************************
publicstaticbool CheckFunds (int acct, double val)
{
SqlConnection connection = getConnection();
SqlCommand command = new SqlCommand(
"STCheckFunds", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@account",acct);
command.Parameters.Add("@amount",val);
SqlParameter retValue = command.Parameters.Add(
"ReturnValue",SqlDbType.Bit);
retValue.Direction = ParameterDirection.ReturnValue;
connection.Open();
command.ExecuteNonQuery();
sbyte result = Convert.ToSByte(
command.Parameters["ReturnValue"].Value);
connection.Close();
if(result == 0) returnfalse;
elsereturntrue;
}
//************************************************
// Checks for stock quantity before placing a sell Order
// returns 1 if sufficient stocks are available to order // else 0
//************************************************
publicstaticbool CheckStocks (int acct, string sym,
int qty)
{
SqlConnection connection = getConnection();
SqlCommand command = new SqlCommand(
"STCheckStocks", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@account",acct);
command.Parameters.Add("@symbol",sym);
command.Parameters.Add("@quantity",qty);
SqlParameter retValue = command.Parameters.Add(
"ReturnValue",SqlDbType.Bit);
retValue.Direction = ParameterDirection.ReturnValue;
connection.Open();
command.ExecuteNonQuery();
sbyte result = Convert.ToSByte(
command.Parameters["ReturnValue"].Value);
connection.Close();
if(result == 0) returnfalse;
elsereturntrue;
}
privatestatic SqlConnection getConnection()
{
returnnew SqlConnection(dlStockTrade.strConnection);
}
}
}
3.2Implementation of Business Logic Layer
Below are the definitions of all the classes used in implementation of the business logic.
3.2.1Class ‘Order’
using System;
using System.Data;
using System.Configuration;
using System.Text;
using System.Data.SqlClient;
using System.Collections;
using StockTrade.Components.DLL;
namespace StockTrade.Components.BLL
{
//************************************************
// Order Class used to represent an Order
//************************************************
publicclass Order
{
privateintaccountId;
privatestringsymbol;
privateboolbuyOrSell;
privateintquantity;
privatedoublepricePlaced;
privatedoublepriceExecuted;
//default constructor
public Order() { }
public Order (int acct, string ticker, bool bs, int qty,
double placed, double exec)
{
accountId = acct;
symbol = ticker;
buyOrSell = bs;
quantity = qty;
pricePlaced = placed;
priceExecuted = exec;
}
//************************************************ // set and get Properties
//************************************************ publicint AccountId
{
get{ return accountId; }
set{ accountId = value; }
}
publicstring Symbol
{
get{ return symbol; }
set{ symbol = value; }
}
publicint Quantity
{
get{ return quantity; }
set{ quantity = value; }
}
publicbool BuyOrSell
{
get{ return BuyOrSell; }
set{ BuyOrSell = value; }
}
publicdouble PricePlaced
{
get{ return pricePlaced; }
set{ pricePlaced = value; }
}
publicdouble PriceExecuted
{
get{ return priceExecuted; }
set{ priceExecuted = value; }
}
//************************************************
// Places a Order, returns orderId, -1 for invalid
// ticker, 0 for other invalid data
//************************************************ publicstaticint PlaceOrder (int acct, string sym,
bool bs, int qty, double placed)
{
return dlStockTrade.PlaceOrder(acct, sym, bs,
qty, placed);
}
//************************************************ // Checks for funds before placing a Order
// returns 1 if sufficient funds are available
// to order else returns 0
//************************************************ publicstaticbool CheckFunds (int acct, double val)
{
return dlStockTrade.CheckFunds(acct, val);
}
//************************************************ // Checks for stock quantity before placing a sell Order
// returns 1 if sufficient stocks are available
// to order else 0
//************************************************ publicstaticbool CheckStocks (int acct, string sym, int qty)
{
return dlStockTrade.CheckStocks(acct, sym, qty);
}
}
}
3.2.2Class ‘Portfolio’
using System;
using System.Data;
using System.Configuration;
using System.Text;
using System.Data.SqlClient;
using System.Collections;
using StockTrade.Components.DLL;
namespace StockTrade.Components.BLL
{
//************************************************
// Portfolio Class Represents a Portfolio
//************************************************
publicclass Portfolio
{
privateintaccountId;
privatestringticker;
privatestringdescription;
privateintquantity;
privatedoublecurrValue;
privatedoubletotal;
// default constructor
public Portfolio() { }
public Portfolio (int acctId, string ticker, string desc,
int qty, double val)
{
accountId = acctId;
ticker = ticker;
description = desc;
quantity = qty;
currValue = val;
}
//************************************************
// set and get Properties
//************************************************ publicint AccountId
{
get{ return accountId; }
set{ accountId = value; }
}
publicstring Item
{
get{ return ticker; }
set{ ticker = value; }
}
publicstring Ticker