結合論壇使用者操作談asp.net表單驗證(上)
有了前面的知識,現在我們要進入實戰。做過asp的朋友都知道表單驗證是個比較頭疼的問題,有經驗的Web程式員有這麼一句話,那就是用戶端不相信伺服器端,伺服器端不相信用戶端。
什麼意思呢,就是說做表單驗證時伺服器端程式不能假定用戶端程式是正確的而不加檢測,這樣如果用戶端關閉javascript就可能造成出錯,而如果只做伺服器端檢測,那麼需要提交到伺服器端再返回,那麼效率會大打折扣,並且對於使用者極不方便。所以只能用戶端和伺服器端做兩次驗證。現在asp.net提供了新的表單驗證機制,下面我將結合執行個體簡單講一下,想要瞭解asp.net提供的幾個驗證webcontrol的詳細資料,可以參照我的asp+初級教程。
在講表單驗證以前,先做點準備工作。前面談到用asp.net開發需要轉換編程思維,也就是用物件導向的思想去考慮問題,bbs對象我們已經構造好了,現在讓我們來看一下一個論壇系統中另外一個很重要的對象:使用者。可以說,論壇系統的主體是使用者,沒有使用者那也就談不上什麼論壇了,
所以圍繞使用者的操作很多,比如說添加/刪除使用者,查詢/修改使用者資料等等,有些論壇還有積分機制,根據使用者登入次數或發言多少來決定積分,已表明該使用者的活躍程度。那麼,我們應該如何來構造論壇使用者這個對象呢?看看下面的類定義:
namespace MyOwnClass
{
using System;
using MyOwnClass ;
using System.Data.SQL ;
using System.Web.Util ;
////////////////////////////////////////////////////////////////////
//
// Class Name : BBSUser
//
// Description: 論壇使用者類,構造一個論壇使用者物件
//
// date: 2000/02/03
//
/// ////////////////////////////////////////////////////////////////
public class BBSUser
{
//建立枚舉類型,建立使用者方式,建立還是修改
public enum CreateType
{
Create = 0 ,
Modify
}
//私人成員變數
private int m_intID ; //使用者ID
private string m_strUserName ; //使用者名稱
private string m_strPassword ; //密碼
private string m_strEmail ; //使用者email
private string m_strHomepage ; //個人首頁
private string m_strSignature ; //簽名
//屬性,全部唯讀
public int ID
{
get
{
return m_intID ;
}
}
public string UserName
{
get
{
return m_strUserName ;
}
}
public string Password
{
get
{
return m_strPassword ;
}
}
public string Email
{
get
{
return m_strEmail ;
}
}
public string Homepage
{
get
{
return m_strHomepage ;
}
}
public string Signature
{
get
{
return m_strSignature ;
}
}
//建構函式
public BBSUser()
{
//
// TODO: Add Constructor Logic here
//
m_strUserName = "" ;
m_strPassword = "" ;
m_strEmail = "" ;
m_strHomepage = "" ;
m_strSignature = "" ;
}
//根據使用者名稱查詢使用者資料
public bool GetUser(string a_strUserName)
{
//如果使用者名稱中包含單引號則拋出一個異常
if (a_strUserName.IndexOf("'") != -1)
{
throw(new Exception("使用者名稱包含非法字元")) ;
}
bool bExists = false ;
MyConnection myConn = new MyConnection() ;
try
{
myConn.Open() ;
SQLCommand myCommand = new SQLCommand() ;
myCommand.ActiveConnection = myConn ;
myCommand.CommandText = "select * from BBSUser where
UserName='" + a_strUserName + "'";
SQLDataReader myReader ;
myCommand.Execute(out myReader) ;
if (myReader.Read())
{
m_intID = (int)myReader["ID"] ;
m_strUserName = myReader["UserName"].ToString() ;
m_strPassword = myReader["password"].ToString() ;
m_strEmail = myReader["Email"].ToString() ;
m_strHomepage = myReader["Homepage"].ToString() ;
m_strSignature = myReader["Signature"].ToString() ;
bExists = true ;
}
else
{
bExists = false ;
}
myReader.Close() ;
myConn.Close() ;
}
catch(SQLException e) //如果出現異常
{
throw(new Exception("資料庫異常:" + e.Message)) ;
}
//返回結果
return bExists ;
}
//重載,根據使用者ID尋找使用者
public bool GetUser(int a_intUserID)
{
bool bExists = false ;
MyConnection myConn = new MyConnection() ;
try
{
myConn.Open() ;
SQLCommand myCommand = new SQLCommand() ;
myCommand.ActiveConnection = myConn ;
myCommand.CommandText = "select * from BBSUser where id=" +
a_intUserID.ToString() ;
SQLDataReader myReader ;
myCommand.Execute(out myReader) ;
if (myReader.Read())
{
m_intID = (int)myReader["ID"] ;
m_strUserName = myReader["UserName"].ToString() ;
m_strPassword = myReader["password"].ToString() ;
m_strEmail = myReader["Email"].ToString() ;
m_strHomepage = myReader["Homepage"].ToString() ;
m_strSignature = myReader["Signature"].ToString() ;
bExists = true ;
}
else
{
bExists = false ;
}
myReader.Close() ;
myConn.Close() ;
}
catch(SQLException e) //如果出現異常
{
throw(new Exception("資料庫異常:" + e.Message)) ;
}
//返回結果
return bExists ;
}
//建立使用者
public void CreateUser(BBSUser.CreateType a_enumCreateType ,string
a_strUserName ,
string a_strPassword ,
string a_strEmail ,
string a_strHomepage ,
string a_strSignature)
{
//監測參數有效性
if (a_strUserName.IndexOf("'") != -1 || a_strPassword.IndexOf("'")
!= -1
|| a_strEmail.IndexOf("'") != -1 ||
a_strHomepage.IndexOf("'") != -1
|| a_strSignature.IndexOf("'") != -1)
{
throw(new Exception("包含非法字元")) ;
}
try
{
MyOwnClass.MyConnection myConn = new MyConnection() ;
SQLCommand myCmd = new SQLCommand() ;
//判斷是建立使用者還是修改使用者資料
if (a_enumCreateType == BBSUser.CreateType.Create)
{
myCmd.CommandText = "insert into BBSUser(UserName ,
Password , Email , Homepage , Signature)"
+ "values('" + a_strUserName + "','"
+ a_strPassword + "','"
+ a_strEmail + "','" + a_strHomepage
+ "','" + a_strSignature + "')" ;
}
else
{
myCmd.CommandText = "update BBSUser set Email='" +
a_strEmail
+ "' , Homepage='" + a_strHomepage + "' ,
Signature='"
+ a_strSignature + "' where username='" +
a_strUserName + "'";
}
myConn.Open() ;
myCmd.ActiveConnection = myConn ;
myCmd.ExecuteNonQuery() ;
myConn.Close() ;
}
catch(SQLException exp)
{
throw(new Exception("資料庫出錯:" + exp.Message)) ;
}
}
//取回密碼
public void GetPassword(string a_strUserName , string a_strEmail)
{
if (GetUser(a_strUserName) && m_strEmail == a_strEmail)
{
//發送Email
System.Web.Util.MailMessage myMail = new MailMessage() ;
myMail.From = "lyp@server1.domain" ;
myMail.Subject = "取回您的密碼" ;
myMail.Body = "請牢記您的密碼:" + m_strPassword ;
myMail.To = a_strEmail ;
SmtpMail.Send(myMail) ;
}
else
{
throw (new Exception("該使用者不存在")) ;
}
}
}
}
通過前面的學習,你可能已經能夠看懂這個類定義的大部分內容,那些是成員變數,那些是屬性,那些是方法都可以理解了,在這裡需要解釋的只有以下兩部分內容,首先看這段代碼:
public enum CreateType
{
Create = 0 ,
Modify
}
這段代碼的作用是建立BBSUser類的一個枚舉變數,寫過c程式的朋友很容易理解,建立這個枚舉變數的作用是簡化記憶,用容易記憶的名稱代替值,比如上邊這個定義,當在方法CreateUser裡作為第一個參數時,BBSUser.CreateType.Create實際的值是0,代表這個方法的目的是建立使用者,而如果是BBSUser.CreateType.Modify,則代表目的是修改使用者資料。顯而易見,用if (a_enumCreateType == BBSUser.CreateType.Create)這樣的語句比用if (a_intCreateTYpe == 1)更容易記憶,最大限度減少出錯的可能。
另外一個要解釋的內容是:你可能已經注意到在類的定義中有兩個 GetUser方法的定義,其範圍和傳回值都相同,只是參數類型不同。沒錯,這種做法叫重載(override),是並且只能是物件導向程式語言實現多態性的基本方法,那麼這樣做有什麼好處呢?就是根據參數不同由類自己決定應該調用那個正確的方法,這樣講可能有些抽象,那麼舉個例子來說吧,這個GetUser方法的作用是取得使用者資料,那麼它可以通過使用者名稱來取得資料,也可以通過使用者ID來取得,如果不用函數的重載,那麼我們需要建兩個函數,可能一個叫GetUserFromName(string a_strName) , 而另一個是GetUserFormID(int a_intID),在調用時需要判斷一下決定調用那個方法,象這樣:
if ( BBSUser.ID != "")
{
GetUserFromID(BBSUser.ID) ;
}
else if(BBSUser.Name != "")
{
GetUserFromName(BBSUser.Name) ;
}
以上兩種方法孰優孰劣恐怕已經不用我說了吧。好了,既然我們已經建立好BBSUser對象,下面就可以利用它來進行對使用者的操作了。