Community Server系列之二:页面之间的关系1[介绍]
当我们第一眼见到CS的时候你是不是被他那么纷繁复杂的结构看傻眼呢。那么在认识CS之前最好对它的页面间关系做一个全面的了解,这对我门改造CS有较大的帮助。
首先我们对整体一个简单的了解,如图,此为在IDE中打开的项目列表:
其中CommunityServerWeb项目为IIS运行的WEB项目,项目的UI层相关的都放在此处。CommunityServerComponents和CommunityServerControls都是支持整个系统运行所必须的组件,其中CommunityServerControls项目里有大量的系统公用的控件,由于本系统的几乎所有页面都是由用户控件组合而成的所以需要先了解在CS中用户控件的分布机制。
我们可以看到,在UI层的Themes文件夹里保存了所有在其他层实现的用户控件的ascx文件,我想有必要介绍一下此目录的结构。
如上图,default文件夹里保存了系统平台使用的默认风格的UI文件,其他文件夹为相应的其他风格的文件集合。当然在此Blogs和Galleries两个文件夹分别是针对博客的皮肤和相册的皮肤,因为这两个项目需要根据具体用户的需要单独制定样式,和网站整体的样式不相关所以单独保存在平行的文件夹里。让我们再看看default文件夹里有些什么,首先是images这个不用说,就是保存了此种风格需要的图片资源,Masters文件夹里保存了页面的整体风格的相关框架,这个在后面详细描述,Skin文件夹里保存的既是大量的用户控件的UI实现,其中命名规则为:skin-ClassName.ascx 其中ClassName为相对应的类名,注意文件名一定要按照这个规则来命名,程序运行的时候,后台的是根据这个名称来找到相应的UI层文件的,这样隔离了依赖关系,前台不用被后台代码束缚了,此种模式我们把它叫着模板用户控件,因为UI层的职责已经很明确了那就是提供控件展现的模板供后台代码调用。
可以这样来看页面执行过程:用户请求aspx的页面à程序查找页面中的用户控件à实例话用户控件à实例化时根据配置找到相应风格相应名称的ascx文件一并实例化à生成关联后的控件对象返回给aspx页面。这样看来,虽然代码分离了,达到的效果却没有变。
问题出现了,后台代码和UI层的同步问题,我们在平时建立用户控件或aspx文件的时候IDE自动为我们生成了很多代码,使得我们不需要考虑前台的控件和后台代码的对应问题,而这里代码和UI是分开的,涉及到增加删减控件不同步的问题。要达到用户在UI层删除一个元素之后页面也不会出错,用户随时需要了可以随时修改回去,在CS中是这样处理的,拿登陆的用户控件来看(\src\Controls\Login.cs&\src\Web\Themes\default\Skins\Skin-Login.ascx)
如图,这是Login在CommunityServerControls项目里的继承关系,我们的重点应该放在TemplatedWebControl这个类里,此类是所有通过模板方式建立用户控件的基类,在这里包含了处理模板相关的功能,比如命名规则自动找到相应的ascx文件等等,这里注意一下这个的方法:protected abstract void AttachChildControls();可以看出此方法为抽象的,而且整个类里也就只有这么一个抽象方法,由继承关系我们知道在Login类里必须实现此方法,此方法的作用是干什么的呢,让我们看看Login类里这个方法都干了些什么:
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
}
}
看了这个我们应该明白了吧,此方法就是我们手动建立相关控件的关联,使用FindControl("controlname")方法我们就可以找到模板的相应控件所以在定制模板的时候模板里的控件的ID一定要和此处一一对应即可。
你一定会想,这样一一对应后每每修改前台模板内的控件后不是都要到相应的后台代码里修改相应的代码,不错,是这样,不过还是有相应的对策来弥补这种不足,那就是在后台尽量把前台需要的功能和代码考虑全,这样在前台如果需要去掉某个控件后台的代码也不需要改变,这里后台代码就应该这样写了:
TextBox name = FindControl("username") as TextBox;
if(name != null)
{
//处理代码
}
这里可以看出,第一句使用了as语句,作用为把找到的对象转换为TextBox类型,如果没找到或类型转换失败也不引发异常而是将NULL付给变量,这样我们在代码里只需要加多判断引用是否为NULL即可按照我们的想法处理相应逻辑了。
怕写太多让人没耐心,故分成几篇来分析,后面将介绍在CS中的模板处理机制。
转载于:https://www.cnblogs.com/Dragonpro/archive/2006/04/24/383097.html
Community Server系列之二:页面之间的关系1[介绍]相关推荐
- 汇川技术小型PLC梯形图编程系列教程(二):AutoShop软件使用技巧介绍
原文链接:汇川技术小型PLC梯形图编程系列教程(二):AutoShop软件使用技巧介绍 俗话说的好,磨刀不误砍柴工.这里的刀指的是准备工作:手册+熟练使用软件(掌握一些技巧).所以本篇为大家简单介绍一 ...
- 计算机底层:ASCII码、区位码、国标码、汉字机内码,还有字形码和输入输出编码之间的关系以及介绍
计算机底层:ASCII.区位码.国标码.汉字机内码之间的关系,还有字形码和输入输出编码之间的关系以及介绍 键盘上有:数字.字母.符合.这些都称作为字符,而它们的组合就叫做:字符串. ASCII 键盘上 ...
- Community Server系列之三:页面间关系2[介绍]
CS中几乎所有的页面都是靠模板的呈现方式来实现的,那么CS中有些什么样的模板呢,让我们看看CS中的模板机制吧: 在我们使用IDE打开Default.aspx页面时,我们仅仅看到一些毫无顺序的控件,几乎 ...
- ARM各系列CPU与STM32之间的关系
我用Arm时,最早用的是A8:后来用STM32时,知道了STM32这种类似于单片机之类的东西,其实也是Arm的.至于他们之间的区别和联系,感觉自己好像明白,又不能完全说得清楚,于是抽了个时间好好了整理 ...
- Asp.net页面和Html页面之间的关系
Asp.net页面显然要转化为普通的html页面才能在浏览器中显示,但是对于两者的关系,或者说从服务器在接受请求处理请求这段时间内对asp.net页面的操作一直不是很明白,下边的一段话可以让人豁然开朗 ...
- IT结合测试时,准备数据的注意事项(之二:表之间的关系)。
我们在做数据时,有时有多个表. 这时,也许这两个表之间就有主外键关联,而且关联的不止一个(复合主键) 表1 2009001 1 大连 汽车轮胎 2009001 0 大连 汽车轮胎 表2 20090 ...
- Linq To Sql进阶系列(二)M:M关系
在Linq To Sql进阶系列(一) 一文中,我们谈到了数据库中的两种基本关系1:M 与1:1. 而现实世界中,还有一种M:M 的关系.比如,一个老师可以有多个学生,而一个学生也可以有多个老师.老师 ...
- Spring系列(二):Bean注解用法介绍
今天给大家介绍一下Spring中Bean注解的用法,后续的文章给大家介绍Sping其他注解用法,希望对大家日常工作能有所帮助! 1.首先创建一个maven项目引入spring依赖 <depend ...
- 项目分享三:页面之间的传值
一.回调函数的使用 我们首先来看一下,页面间传值的一个经典例子,列表页与明细页之间的传值,如下面二张图所图.在列表页点击评价晒单,进入评价晒单页面,当用户在该页面完成操作后,列表页对应的选项,相应地改 ...
最新文章
- C/C++多个链接库含有同名函数,编译会报错吗
- 【文件处理】——字典写入json文件或TXT文件,读取文件中的字典TypeError: Object of type ‘ndarray‘ is not JSON serializable错误解决方法
- postgresql 远程用户_构建Python pandas基于SSH远程MySQL和PostgreSQL的数据分析
- java生成xml_在JAVA生成XML文件
- 【IT】学生数据库小结2
- android 8.0 iso6,微信8.0.6更新了什么?IOS系统微信8.0.6版本更新详情一览[多图]
- 接口测试工具——postman
- PADS layout 元件之间尺寸标注
- Warning the user/local/mysql/data directory is not owned by the mysql user
- 【AD18】原理图生成PDF
- 条码打印软件如何添加新字体
- 字节跳动java面试题,附详细答案解析
- freemarker导出word如何换行
- 《佛密诸事》第二章 宇宙诸现象
- 【知识分享】C语言的设计模式——责任链、观察者
- UBLOX F9P 高精度GNSS定位板卡的基准站,流动站设置与简单的短基线单主机双模块RTK设置
- JZOJ.4377[GDOI2016模拟3.10]习用之语 解题报告
- 华为鸿蒙战略发布会视频,华为公布鸿蒙手机操作系统开机画面视频
- 【学习资料】中国开放大学-电大-《教育学》形考作业答案(2018).docx
- 如何配置java的环境变量
热门文章
- kbengine0.2.3发布,开源分布式游戏服务端引擎
- 指针数组,数组指针,指针函数,函数指针,二级指针详解
- 简述Java内存模型的由来、概念及语义
- DHTML【8】--CSS
- Silverlight专题(WatermarkedTextBox使用)--摘录 很受用
- chrome浏览器下“多余”的2px
- 中柏平板触摸驱动_工业平板电脑触摸屏种类及故障解决办法,赶紧收藏起来
- 写文件 —— 将内容按照指定格式写入配置文件(fwrite()函数-》》向指定的文件中写入若干数据块)
- openLDAP的编译安装以及配置
- MYSQL密码解密函数的使用