我的主要突破口是账户管理这一部分,主要是账户的注册,登陆等,里面就涉及到了数据库操作。整个petshop自身还分成若干个项目显示层的是Web项目,业务逻辑层的是BLL项目,接口层是IDAL,还有相应的DALFactory来动态的决定具体绑定哪一个数据库,数据库的类型有两个,一种是Oracle,还有SQL Server,他们里面的Account都是动态的继承自IDAL里面的IAccount接口,比较这样使逻辑层和数据库层隔离,可以对多个数据库支持,如果修改逻辑,只需要对逻辑层里面的接口编码就可以了。我以后应该只会做一些应用,具体的绑定到某一个特定的数据库上,但是工厂模式还是需要好好理解一下的。
我从显示层Web层入手,看到了这样的一些方面,首先就是分层的概念,如果需要注册一个用户,从逻辑上分成三部分,账户的基本部分,包括用户名密码和Email,然后是用户的详细信息部分,制作成为了一个控件包括地址等信息,很有意思有真实姓名,所在国家城市之类的,发现这个东西居然不是联动的,前些日子做了一个动态选学生,根据院系专业年级类别五级联动的例子,可以整合在一起。这个控件在Controls这个目录下叫做AddressUI.ascx,封装了相应的ui和代码,值得提一下的就是这个类对应的get,set一段代码.
using PetShop.Model; using PetShop.BLL; using System.Web.UI; using System.Web.UI.WebControls; namespace PetShop.Web.Controls { public abstract class AddressUI : System.Web.UI.UserControl { protected System.Web.UI.WebControls.TextBox txtFirstName; protected System.Web.UI.WebControls.TextBox txtLastName; protected System.Web.UI.WebControls.TextBox txtAddress1; protected System.Web.UI.WebControls.TextBox txtAddress2; protected System.Web.UI.WebControls.TextBox txtCity; protected System.Web.UI.WebControls.TextBox txtZip; protected System.Web.UI.WebControls.TextBox txtPhone; protected System.Web.UI.WebControls.DropDownList listState; protected System.Web.UI.WebControls.RequiredFieldValidator valFirstName; protected System.Web.UI.WebControls.RequiredFieldValidator valLastName; protected System.Web.UI.WebControls.RequiredFieldValidator valAddress1; protected System.Web.UI.WebControls.RequiredFieldValidator valCity; protected System.Web.UI.WebControls.RequiredFieldValidator valZip; protected System.Web.UI.WebControls.RequiredFieldValidator valPhone; protected System.Web.UI.WebControls.DropDownList listCountry; private void InitializeComponent() { } // Page property to set or get the address public AddressInfo Address { get { // Make sure we clean the input string firstName = WebComponents.CleanString.InputText(txtFirstName.Text, 50); string lastName = WebComponents.CleanString.InputText(txtLastName.Text, 50); string address1 = WebComponents.CleanString.InputText(txtAddress1.Text, 50); string address2 = WebComponents.CleanString.InputText(txtAddress2.Text, 50); string city = WebComponents.CleanString.InputText(txtCity.Text, 50); string state = WebComponents.CleanString.InputText(listState.SelectedItem.Text, 2); string zip = WebComponents.CleanString.InputText(txtZip.Text, 10); string country = WebComponents.CleanString.InputText(listCountry.SelectedItem.Text, 50); string phone = WebComponents.CleanString.InputText(txtPhone.Text, 10); return new AddressInfo(firstName, lastName, address1, address2, city, state, zip, country, phone); } set { txtFirstName.Text = value.FirstName; txtLastName.Text = value.LastName; txtAddress1.Text = value.Address1; txtAddress2.Text = value.Address2; txtCity.Text = value.City; txtZip.Text = value.Zip; txtPhone.Text = value.Phone; listState.SelectedItem.Value = value.State; listCountry.SelectedItem.Value = value.Country; } } } } |
这里面有一段代码:
using System; using System.Text; namespace PetShop.Web.WebComponents { /// <summary> /// A sample class to clean the input into web pages /// </summary> public sealed class CleanString { public static string InputText(string inputString, int maxLength) { StringBuilder retVal = new StringBuilder(); // check incoming parameters for null or blank string if ((inputString != null) && (inputString != String.Empty)) { inputString = inputString.Trim(); //chop the string incase the client-side max length //fields are bypassed to prevent buffer over-runs if (inputString.Length > maxLength) inputString = inputString.Substring(0, maxLength); //convert some harmful symbols incase the regular //expression validators are changed for (int i = 0; i < inputString.Length; i++) { switch (inputString[i]) { case '"': retVal.Append("""); break; case '<': retVal.Append("<"); break; case '>': retVal.Append(">"); break; default: retVal.Append(inputString[i]); break; } } // Replace single quotes with white space retVal.Replace("'", " "); } return retVal.ToString(); } } }
|
这段东西主要作用就是对于一些html的特殊字符进行转义,也比较简单,但是可以直接把输入进行转义,比如你输入“自来 也”,那么这段东西在存储的时候就储存成了“自来 也”,这样显示的时候和存储在数据库的时候,就一直了,我觉得还比较有用,对于一些懂html知识的人来讲是个屏蔽,比如他的用户名输入为<font color="red">nyy</font>那么这个时候,就自动显示为红色了,这个方法可以进行控制,原样输出,很好。
profile里面记录一些用户的习惯,作为一个新的控件来装载,存储着显示语言,默认宠物的category,这样的东西。然后就是写数据库,我只看对于sql server而言的,比较简单:
public void Insert(AccountInfo acc) { SqlParameter[] signOnParms = GetSignOnParameters(); SqlParameter[] accountParms = GetAccountParameters(); SqlParameter[] profileParms = GetProfileParameters(); signOnParms[0].Value = acc.UserId; signOnParms[1].Value = acc.Password; SetAccountParameters(accountParms, acc); SetProfileParameters(profileParms, acc); using (SqlConnection conn = new SqlConnection(SQLHelper.CONN_STRING_NON_DTC)) { conn.Open(); using (SqlTransaction trans = conn.BeginTransaction()) { try { SQLHelper.ExecuteNonQuery(trans, CommandType.Text, SQL_INSERT_SIGNON, signOnParms); SQLHelper.ExecuteNonQuery(trans, CommandType.Text, SQL_INSERT_ACCOUNT, accountParms); SQLHelper.ExecuteNonQuery(trans, CommandType.Text, SQL_INSERT_PROFILE, profileParms); trans.Commit(); }catch { trans.Rollback(); throw; } } } } |
传进来的参数是一个Entity类的东西,里面存着我们需要的注册需要的属性,第一步就是把相应的parameter赋好,然后开始try,以后自己用的时候注意它的try catch的写法,需要对SqlTransaction 进行相应的commit和rollback,在SQLHelper.ExecuteNonQuery就是对SQLCommand的再次封装,存储了,他的语句就是普通的insert into ,并没有调用存储过程,我想也是因为insert没有必要作存储过程,没有太大的数据量,select就不行了。很晚了,还没吃饭,下一步就是找到登陆时是怎么做的,怎么操作Session的
最后,我们来看一下,登陆是怎么做的。
public bool ProcessLogin(string userId, string password){
// Use the account business logic layer to login
Account account = new Account();
AccountInfo myAccountInfo = account.SignIn(userId, password);
//If login is successful then store the state in session and redirect
if (myAccountInfo != null) {
HttpContext.Current.Session[ACCOUNT_KEY] = myAccountInfo;
// Determine where to redirect the user back too
// If they came in from the home page, take them to a similar page
if (FormsAuthentication.GetRedirectUrl(userId, false).EndsWith(URL_DEFAULT)) {
FormsAuthentication.SetAuthCookie(userId, false);
HttpContext.Current.Response.Redirect(URL_ACCOUNTSIGNIN, true);
}else{
// Take the customer back to where the came from
FormsAuthentication.SetAuthCookie(userId, false);
HttpContext.Current.Response.Redirect(FormsAuthentication.GetRedirectUrl(userId, false), true);
}
return true;
}else {
// Login has failed so return false
return false;
}
}
存储在session里面,很通用的做法。我应该动手了。