Community Server系列之二:页面之间的关系1[介绍]
?????? 當我們第一眼見到CS的時候你是不是被他那么紛繁復雜的結(jié)構(gòu)看傻眼呢。那么在認識CS之前最好對它的頁面間關(guān)系做一個全面的了解,這對我門改造CS有較大的幫助。
?????? 首先我們對整體一個簡單的了解,如圖,此為在IDE中打開的項目列表:
?
?????? 其中CommunityServerWeb項目為IIS運行的WEB項目,項目的UI層相關(guān)的都放在此處。CommunityServerComponents和CommunityServerControls都是支持整個系統(tǒng)運行所必須的組件,其中CommunityServerControls項目里有大量的系統(tǒng)公用的控件,由于本系統(tǒng)的幾乎所有頁面都是由用戶控件組合而成的所以需要先了解在CS中用戶控件的分布機制。
CS用戶控件:我們知道,用戶控件一般以.ascx為擴展名,在建立時都自帶了相應(yīng)的.cs文件,而在CS中考慮到明晰的分層結(jié)構(gòu)和方便的修改UI以及最大程度的換膚功能,程序使用了后臺代碼與前臺UI分開在兩個層中,拿常用的CommunityServerControls這個項目來說在項目里我們看不到ascx文件的蹤影,原來ascx文件保存在UI層,并且按照各種風格定義了不一樣的ascx文件,具體的路徑可以參照下圖的導航找到:?
??????? 我們可以看到,在UI層的Themes文件夾里保存了所有在其他層實現(xiàn)的用戶控件的ascx文件,我想有必要介紹一下此目錄的結(jié)構(gòu)。
??????? 如上圖,default文件夾里保存了系統(tǒng)平臺使用的默認風格的UI文件,其他文件夾為相應(yīng)的其他風格的文件集合。當然在此Blogs和Galleries兩個文件夾分別是針對博客的皮膚和相冊的皮膚,因為這兩個項目需要根據(jù)具體用戶的需要單獨制定樣式,和網(wǎng)站整體的樣式不相關(guān)所以單獨保存在平行的文件夾里。讓我們再看看default文件夾里有些什么,首先是images這個不用說,就是保存了此種風格需要的圖片資源,Masters文件夾里保存了頁面的整體風格的相關(guān)框架,這個在后面詳細描述,Skin文件夾里保存的既是大量的用戶控件的UI實現(xiàn),其中命名規(guī)則為:skin-ClassName.ascx 其中ClassName為相對應(yīng)的類名,注意文件名一定要按照這個規(guī)則來命名,程序運行的時候,后臺的是根據(jù)這個名稱來找到相應(yīng)的UI層文件的,這樣隔離了依賴關(guān)系,前臺不用被后臺代碼束縛了,此種模式我們把它叫著模板用戶控件,因為UI層的職責已經(jīng)很明確了那就是提供控件展現(xiàn)的模板供后臺代碼調(diào)用。
??????? 可以這樣來看頁面執(zhí)行過程:用戶請求aspx的頁面à程序查找頁面中的用戶控件à實例話用戶控件à實例化時根據(jù)配置找到相應(yīng)風格相應(yīng)名稱的ascx文件一并實例化à生成關(guān)聯(lián)后的控件對象返回給aspx頁面。這樣看來,雖然代碼分離了,達到的效果卻沒有變。
問題出現(xiàn)了,后臺代碼和UI層的同步問題,我們在平時建立用戶控件或aspx文件的時候IDE自動為我們生成了很多代碼,使得我們不需要考慮前臺的控件和后臺代碼的對應(yīng)問題,而這里代碼和UI是分開的,涉及到增加刪減控件不同步的問題。要達到用戶在UI層刪除一個元素之后頁面也不會出錯,用戶隨時需要了可以隨時修改回去,在CS中是這樣處理的,拿登陸的用戶控件來看(\src\Controls\Login.cs&\src\Web\Themes\default\Skins\Skin-Login.ascx)??? 如圖,這是Login在CommunityServerControls項目里的繼承關(guān)系,我們的重點應(yīng)該放在TemplatedWebControl這個類里,此類是所有通過模板方式建立用戶控件的基類,在這里包含了處理模板相關(guān)的功能,比如命名規(guī)則自動找到相應(yīng)的ascx文件等等,這里注意一下這個的方法:protected abstract void AttachChildControls();可以看出此方法為抽象的,而且整個類里也就只有這么一個抽象方法,由繼承關(guān)系我們知道在Login類里必須實現(xiàn)此方法,此方法的作用是干什么的呢,讓我們看看Login類里這個方法都干了些什么:
login.cs
head#region?head
//------------------------------------------------------------------------------
//?<copyright?company="Telligent?Systems">
//?????Copyright?(c)?Telligent?Systems?Corporation.??All?rights?reserved.
//?</copyright>?
//------------------------------------------------------------------------------
using?System;
using?System.Web;
using?System.Web.Security;
using?System.Web.UI;
using?System.Web.UI.WebControls;
using?CommunityServer.Components;
#endregion
namespace?CommunityServer.Controls?
{
????[
????????ParseChildren(true)
????]
????public?class?Login?:?SecureTemplatedWebControl?{
????????CSContext?csContext?=?CSContext.Current;
????????TextBox?username;
????????TextBox?password;
????????IButton?loginButton;
????????CheckBox?autoLogin;
????????Other?Code#region?Other?Code
????????//?*********************************************************************
????????//??Login
????????//
????????/**////?<summary>
????????///?Constructor
????????///?</summary>
????????//?***********************************************************************/
????????public?Login()?:?base()?
????????{
????
????????}
????????protected?string?ReferralLink
????????{
????????????get
????????????{
????????????????return?ViewState["ReferralLink"]?as?string;
????????????}
????????????set
????????????{
????????????????ViewState["ReferralLink"]?=?value;
????????????}
????????}
????????protected?override?void?OnInit(EventArgs?e)
????????{
????????????this.EnableViewState?=?true;
????????????base.OnInit?(e);
????????}
????????protected?override?void?OnLoad(EventArgs?e)
????????{
????????????base.OnLoad?(e);
????????????if(!Page.IsPostBack)
????????????{
????????????????Uri?referral?=??Context.Request.UrlReferrer;
????????????????if(referral?!=?null)
????????????????????ReferralLink?=?referral.ToString();
????????????}
????????}
????????//?*********************************************************************
????????//??CreateChildControls
????????//
????????/**////?<summary>
????????///?This?event?handler?adds?the?children?controls.
????????///?</summary>
????????//?***********************************************************************/
????????protected?override?void?CreateChildControls()?
????????{
????????????//?If?the?user?is?already?authenticated?we?have?no?work?to?do
????????????if(Page.Request.IsAuthenticated)
????????????{
????????????????//?If?the?URL?is?for?the?login?page?and?the?user?is?already?logged?in
????????????????//?we?need?to?throw?an?access?denied?exception
????????????????if?(Globals.GetSiteUrls().Login.StartsWith(csContext.Context.Request.Path))?
????????????????????throw?new?CSException?(CSExceptionType.UserAlreadyLoggedIn,?csContext.ReturnUrl);
????????????????return;
????????????}
????????????base.CreateChildControls();
????????}
????????#endregion
????????protected?override?void?AttachChildControls()
????????{
????????????//?Find?the?username?control
????????????username?=?(TextBox)?FindControl("username");
????????????//?Find?the?password?control
????????????password?=?(TextBox)?FindControl("password");
????????????//?Find?the?login?button
????????????loginButton?=?ButtonManager.Create(FindControl("loginButton"));
????????????loginButton.Click?+=?new?EventHandler(LoginButton_Click);
????????????loginButton.Text?=?ResourceManager.GetString("LoginSmall_Button");
????????????//?Find?the?autologin?checkbox
????????????autoLogin?=?(CheckBox)?FindControl("autoLogin");
????????????autoLogin.Text?=?ResourceManager.GetString("LoginSmall_AutoLogin");????????
????????????//autoLogin.AutoPostBack?=?true;
????????????//autoLogin.CheckedChanged?+=?new?EventHandler(?AutoLogin_OnCheckedChanged?);
????????????
????????????//?Restore?autologin?status?from?the?auto?login?cookie
????????????AutoLoginCookie?alCookie?=?new?AutoLoginCookie();
????????????autoLogin.Checked?=?alCookie.GetValue();
????????????RegisterSetFocusScript();
????????}
????????Other?Codes#region?Other?Codes
????????/**////?<summary>
????????///?Event?handler?to?update?auto?login?cookie?value.
????????///?</summary>
????????protected?void?AutoLogin_OnCheckedChanged?(Object?sender,?EventArgs?e)?
????????{
????????????AutoLoginCookie?alCookie?=?new?AutoLoginCookie();
????????????alCookie.Write(?autoLogin.Checked?);
????????}
????????//?*********************************************************************
????????//??LoginButton_Click
????????//
????????/**////?<summary>
????????///?Event?handler?to?handle?the?login?button?click?event
????????///?</summary>
????????//?***********************************************************************/
????????public?void?LoginButton_Click?(Object?sender,?EventArgs?e)?{
????????????User?userToLogin?=?new?User();
????????????string?redirectUrl?=?null;
????????????//?Save?in?cookie?auto?login?user's?preference
????????????//?only?if?it?wasn't?previously?set?or?the?cookie?value?differs?from
????????????//?login's?autologin?checkbox?status.
????????????//
????????????AutoLoginCookie?alCookie?=?new?AutoLoginCookie();
????????????if?(!alCookie.HasValue?||
????????????????(alCookie.HasValue?&&?(alCookie.GetValue()?!=?autoLogin.Checked)))?
????????????{
????????????????alCookie.Write(?autoLogin.Checked?);
????????????}?
????????????if?(!Page.IsValid)
????????????????return;
????????????userToLogin.Username?=?username.Text;
????????????userToLogin.Password?=?password.Text;
????????????
????????????LoginUserStatus?loginStatus?=?Users.ValidUser(userToLogin);
????????????bool?enableBannedUsersToLogin?=?CSContext.Current.SiteSettings.EnableBannedUsersToLogin;
????????????
????????????//?Change?to?let?banned?users?in
????????????//
????????????if?(loginStatus?==?LoginUserStatus.Success?||?
????????????????(enableBannedUsersToLogin?&&?loginStatus?==?LoginUserStatus.AccountBanned))?{
????????????????//?Are?we?allowing?login?
????????????????//?TODO?--?this?could?be?better?optimized
????????????????if?(!CSContext.Current.SiteSettings.AllowLogin?&&?!userToLogin.IsAdministrator)?{
????????????????????throw?new?CSException(CSExceptionType.UserLoginDisabled);
????????????????}
????????????????????HttpCookie?formsAuthCookie;
????????????????formsAuthCookie?=?FormsAuthentication.GetAuthCookie(userToLogin.Username,?autoLogin.Checked);
????????????????UserCookie?userCookie?=?csContext.User.GetUserCookie();
????????????????userCookie.WriteCookie(formsAuthCookie,?30,?autoLogin.Checked);
????????????????//?Get?the?link?from?the?context
????????????????if?((CSContext.Current.ReturnUrl?!=?null)?&&?(CSContext.Current.ReturnUrl.Trim()?!=?string.Empty))
????????????????????redirectUrl?=?CSContext.Current.ReturnUrl;
????????????????//?If?none,?get?the?stored?redirect?url
????????????????if?((redirectUrl?==?null)?&&?(ReferralLink?!=?null)?&&?(ReferralLink.Trim()?!=?string.Empty))
????????????????????redirectUrl?=?ReferralLink;
????????????????//?Check?to?ensure?we?aren't?redirecting?back?to?a?Message?prompt?or?back?to?the?logout?screen
????????????????//?Or?ChangePassword*,?or?CreateUser*,?or?EmailForgottenPassword*
????????????????//?Or,?if?no?URL,?use?appPath
????????????????if?(Globals.IsNullorEmpty(redirectUrl)
????????????????????||?(redirectUrl.IndexOf("MessageID")?!=?-1)
????????????????????||?(redirectUrl.IndexOf(Globals.GetSiteUrls().Logout)?!=?-1)
????????????????????||?(redirectUrl.IndexOf("ChangePassword")?!=?-1)
????????????????????||?(redirectUrl.IndexOf("EmailForgottenPassword")?!=?-1))
????????????????????redirectUrl?=?Globals.GetSiteUrls().Home;
????????????????LeaveSecureConnection(redirectUrl);
????????????}
????????????else?if?(loginStatus?==?LoginUserStatus.InvalidCredentials)?{?
????????????????//?Invalid?Credentials
????????????????Page.Response.Redirect(?Globals.GetSiteUrls().Message(CSExceptionType.UserInvalidCredentials),?true?);
????????????}?
????????????else?if?(loginStatus?==?LoginUserStatus.AccountPending)?{?
????????????????//?Account?not?approved?yet
????????????????Page.Response.Redirect(?Globals.GetSiteUrls().Message(CSExceptionType.UserAccountPending),?true?);
????????????}?
????????????else?if?(loginStatus?==?LoginUserStatus.AccountDisapproved)?{?
????????????????//?Account?disapproved
????????????????Page.Response.Redirect(?Globals.GetSiteUrls().Message(CSExceptionType.UserAccountDisapproved),?true?);
????????????}
????????????else?if?(loginStatus?==?LoginUserStatus.UnknownError)?{?
????????????????//?Unknown?error?because?of?miss-syncronization?of?internal?data
????????????????throw?new?CSException(CSExceptionType.UserUnknownLoginError);
????????????}
????????????//?Reject?banned?users?if?they?are?not?allowed?to
????????????//?pass?through?login.
????????????//
????????????else?if?(!enableBannedUsersToLogin?&&?loginStatus?==?LoginUserStatus.AccountBanned)?{?
????????????????//?Account?banned
????????????????Page.Response.Redirect(?Globals.GetSiteUrls().Message(CSExceptionType.UserAccountBanned),?true?);
????????????}
????????}
????????private?void?RegisterSetFocusScript()
????????{
????????????string?key?=?"LoginOnFocus";
????????????if(Page.IsStartupScriptRegistered(key))
????????????????return;
????????????string?script?=?@"
????????????????????<script?language=""javascript"">
????????????????????<!--
????????????????????????document.forms[0].{0}.focus()
????????????????????-->
????????????????????</script>";
??????
????????????Page.RegisterStartupScript("LoginOnFocus",?string.Format(script,?username.ClientID)?)?;
????????????
????????}
????????#endregion
????}
}
看了這個我們應(yīng)該明白了吧,此方法就是我們手動建立相關(guān)控件的關(guān)聯(lián),使用FindControl("controlname")方法我們就可以找到模板的相應(yīng)控件所以在定制模板的時候模板里的控件的ID一定要和此處一一對應(yīng)即可。
??????? 你一定會想,這樣一一對應(yīng)后每每修改前臺模板內(nèi)的控件后不是都要到相應(yīng)的后臺代碼里修改相應(yīng)的代碼,不錯,是這樣,不過還是有相應(yīng)的對策來彌補這種不足,那就是在后臺盡量把前臺需要的功能和代碼考慮全,這樣在前臺如果需要去掉某個控件后臺的代碼也不需要改變,這里后臺代碼就應(yīng)該這樣寫了:
TextBox name = FindControl("username") as TextBox;
if(name != null)
{
??? //處理代碼
}
??????? 這里可以看出,第一句使用了as語句,作用為把找到的對象轉(zhuǎn)換為TextBox類型,如果沒找到或類型轉(zhuǎn)換失敗也不引發(fā)異常而是將NULL付給變量,這樣我們在代碼里只需要加多判斷引用是否為NULL即可按照我們的想法處理相應(yīng)邏輯了。
??????? 怕寫太多讓人沒耐心,故分成幾篇來分析,后面將介紹在CS中的模板處理機制。?
轉(zhuǎn)載于:https://www.cnblogs.com/Dragonpro/archive/2006/04/24/383097.html
總結(jié)
以上是生活随笔為你收集整理的Community Server系列之二:页面之间的关系1[介绍]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图像聚类与检索的简单实现(一)
- 下一篇: [浪子学编程][MS Enterpris