.net 如何让linkbutton的隐藏属性根据自己的意愿关闭或泰坦之旅 开启隐藏

页面导航:
→ 正文内容 ASP .NET 控件 不刷新页面
ASP .NET中执行控件(如ImageButton、LinkButton等)命令不刷新页面
在操作时,很多时候希望提交命令之后不刷新页面:1、防止页面拉动,2、防止主框架中刷新丢失当前运行的子界面。
功能需求:在框架中使用ImageButton控件关闭应用程序问询“是否确认退出”,用ImageButton的OnClick事件(C#)中调用JavaScript关闭IE。
问题提出:弹出对话框时,就丢失子界面中的内容,即使你不退出系统,也无法返回原状态。
解决方案:不直接使用ImageButton的OnClick事件(C#),而通过ImageButton的Attributes.Add("OnClick","javascript:...")的方式处理,就能解决这个问题。
1、aspx文件: 代码如下:&!-- aspx文件 --& &asp:ImageButton ID="ImageButton_Close" runat="server" ImageUrl="~/Images/Icons/stop.gif" /&2、C#文件: 代码如下:// .cs文件 // 添加事件,运行JavaScript代码 protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { ImageButton_Close.Attributes.Add("OnClick", "javascript:if(confirm('试试看吧,能成功否?')) "); } }
您可能感兴趣的文章:
上一篇:下一篇:
最 近 更 新
热 点 排 行做项目经理,首先要明白什么是因地制宜、因势利导,只有最合适的,没有什么叫对的,什么叫错的,项目经理最忌讳的就是完美主义倾向,尤其是做技术人员出身的,喜欢寻找标准答案,耽误了工作进度,也迷茫了自己。以下是一位项目经理人对多年工作总结出来一些做项目的个人体会,写出来供大家指点,在讨论过程中共同提高水平。
  项目开始阶段是一个最重要的阶段。项目经理在接手一个新项目的时候,首先要尽可能地多从各个方面了解项目的情况,如:
  1. 这个项目是什么项目,具体大概做什么事情,是谁提出来的,目的是解决什么问题。在国内很多客户都很不成熟的情况下,千万不要根据项目的名称望文生义地去想象项目的目标。一个名为&办公自动化&的项目很有可能在你进场以后一个月才发现客户其实需要的是一个计算机生产管理辅助信息系统系统。前期了解情况的工作越详细,后面的惊讶就越少,项目的风险就越小。
  2.这个项目里牵涉哪些方面的人,如投资方、具体业务干系方、项目建成后的运营方、技术监督方等等,很多项目里除了业主单位的结构很复杂以外,还有一些其他单位也会牵涉进来,如项目监理公司、业主的行业主管机构等。项目经理需要了解每个方面的人对这个项目的看法和期望是什么。事先了解各个方面的看法和期望,可以让你在做项目碰到问题的时候,就每件事情分析哪些人会在什么方面支持你,哪些人会出于什么目的反对你,从而提前准备联合朋友去对抗敌人,让事情向你所希望的方向发展。没有永远的朋友,也没有永远的敌人,只有一致的利益,这句话作为项目经理是一定要记住的;
  3.基本了解了客户的情况后,下面的事情就是了解自己公司各方面对这个项目的看法。首先是高层领导是否重视,这个决定了你在需要资源的时候,公司是否会根据你的要求提供最有力的支持。领导口头肯定是说支持的,你需要做的是了解公司对这个项目的实际期望,是想把项目越做越大还是想赚钱?是想做样板工程还是干脆想敷衍了事,公司领导对项目的态度决定了你做这个项目的战略,而这个战略方针将对你做项目计划产生直接的影响;
  4.在做整体项目计划前,还要大致计算一下你手上的资源。首先是时间,现在市场竞争激烈,往往很多项目要求在几乎不可能的时间范围里完成。对于这一点,你在做项目的风险控制计划的时候要充分考虑。其次是人员,根据项目预算和已往经验,大致计算一下未来的项目小组有多少种角色,每个角色目前公司是否有人,是否能完全归这个项目使用,是否需要另外招聘一些人员,招聘的准备工作要尽早启动。最后就是一些设备的准备,项目所需大件关键设备要尽早预定,以后不管发生设备等人还是人等设备的情况,浪费的都是你的时间;
  5.现在是做项目说明书的时候了。一份好的项目说明书不仅将要做的事情描述得很清楚(主要是讲做什么,而不是说怎么做),而且把如何检查也说明得很透彻。也就是说它不仅说明白了要做哪些事情,也让客户的业务人员(一般不懂技术)知道项目做成什么样就算完成了。简单地说,项目说明书描述项目做哪些事情和每件事情做到什么程度以及如何检查每一个结果。
  6.是到做总体计划的时间了吗?不,你现在已经知道了客户的目标和你手上的资源,那么做计划以前,你还需要和你的经理和客户充分沟通资源的问题。因为很多资源是还不明确的,你需要写一份报告,详细分析这个项目的风险以及对资源的需求情况。如果一些问题不能得到解决的话,将发生什么样的后果。如果资源不够,就要高层改变策略,增加对这个项目的投入。甚至在条件许可的情况下,有些公司会放弃这个项目。总之,没有人能完成一个不可能完成的任务,如果项目经理不能尽早发现风险,那么就只能去当烈士了。
  7. 明白了要做哪些事情和你手上的筹码以及你做这个项目的总体策略,现在是成立项目小组的时候了。很多项目经理都没有自己选择组员的权利,那么,就尽量发挥你的影响力去寻找那些你想要的人吧。成员的组成根据项目不同,相差较大,很难有什么具体要求,但是,一定要有精通客户业务的人,很多小项目里,这个人就是项目经理本人,大项目里会配备行业专家(Industry expert),这样和客户沟通起来才不会鸡同鸭讲,双方才可以相互理解。我经常看到的情况是我们的技术人员和客户交谈时满口的专业术语,结果搞得客户一头雾水,反过来,他还指责客户不懂技术。其实,明白自己想做什么的客户已经是很好的客户了,不知道自己要做什么,更不懂怎么做还要指手画脚的客户到处存在,但是要明白,是客户选择了你,而不是你选择了客户,有了客户你才有工资拿,心平气和一点吧;
8.现在你要面对三群人:你的领导、你的组员和你的客户,和这些人沟通,让他们知道你打算怎么做,什么时候要他们做什么准备这些事情将是你的主要工作。既然沟通这么重要,那些事先定义一下沟通的原则也是一件很要紧的事情。很多沟通原则都是潜规则,如果你在一个部门时间做长了,对这些规则的运用觉得是一件理所应当的事情,但是,你现在面对的是多个部门甚至多个单位,不把沟通规则说清楚,你以后就会吃亏。
  下面的东西看起来无聊,其实还是很管用的:第一个是规定信息的流动方式和介质,是推还是拉。推的意思就是项目经理将主动发布信息,不管通过电话、邮件还是书面方式,保证将信息传达到每个人。这种情况适合小项目,人少;拉的意思就是项目经理就是一个类似web服务器,你自己需要什么信息就去问他。当然,没有项目经理把自己搞得那么累,他会用发布信息到公共介质的方式公布信息,简单的是白板,复杂一点的是项目的公共信息交互区,潜规则就是我发了你没去看就不要说我没告诉你。说这些看似很无聊,其实里面牵涉信息传达不完全的责任问题。
  当然,这些都是指一般的方式,而且不要绝对化,一般情况下,主动沟通和被动访问是同时存在的,尤其是对领导,项目经理更加应该主动去和领导沟通。第二个问题就是文档问题,很多人怕写文档,但是项目经理一定要牢记&好记性不如烂笔头&的道理。有理有时候为什么会说不清呢?就是因为没有证据。所以项目经理开始就要和客户说清楚有些文档是必须签字的,比如项目经理的项目日志,每个星期至少让客户签字,另外所有达成共识的东西,比如会议纪要,甚至领导的讲话记录,都要写成文档,双方签字,这样以后扯皮的时候,就能做到有据可查。记住:说了的就和没说一样,只有写下来大家签字后才算真正发生了的。
  还有一些问题,比如你提交的报告,给领导(包括本方领导和客户领导)做一个选择题,结果领导压住不批,让你无所适从,结果拖延了进度。这时候,你可以等,但是注意要留记录,标明是谁的责任;另外,如果你在开始阶段就和领导商定:如果批示提交三天后没有得到领导答复就算对方同意,这样你就会主动很多。再比如不同事件的审批流程问题:什么等级的事情记录在项目日志里、什么等级的事情要双方项目经理专门签署备忘录、什么等级的事情要双方领导出面签署合同附件等等。事先想得越周到,以后的工作就越主动。
  9.好了,做了很多前期工作,定义了一些游戏规则,现在是坐下来做计划的时候了。这一节,任意找一本项目管理的书都会说得比我好,所以我就少写一点,说一些自己的体会就是了。首先是找几个关键组员,比如客户业务专家、系统分析员等等,做一下项目模块划分工作。项目分成几块去做,每一块完成什么,模块之间的信息如何交换等等。需求定义的是做什么的问题,而这里说的是怎么做的问题。这里要强调一点:完成一个目标有很多种方式,你要选一种你最熟悉的,而不是看上去最完美的,这个思路会让你的项目减少很多风险。有时候客户会被某种新技术打动,坚持要你采用那种新技术,你就应该告诉他:你选我做这个项目,就应该容许我采用自己最喜欢的方式做事情,新技术之所以有诱惑力,就是因为吃亏的人还不多,我不希望你成为第一批受害者。
  采用一个计划会让你的工作更加明确,比如用微软的Project软件,你填写完表格以后,就可以知道这个项目有多少件事情要做,每件事情需要什么资源,他们之间的前后关系如何,消耗的时间有多长,完成后有什么标志等。所有的结果最后用一个叫做甘特图的形式表现出来。你做完这个表以后会惊奇地发现,甘特图上项目的结束时间会远远落后于你的计划结束时间(签合同的人永远不会先征求你的意见的)。当然,学过项目管理的人会大谈什么WBS、优化路径之类的东西,但是我的经验是你再优化也不可能把这些东西安排到计划的时间结束。如果你没碰到这个问题,在我恭喜你挑了一个轻松活之前,请你再去确认你是否罗列了所有要做的事情和正确评估了他们所需要的时间。这时候,你就要考虑牺牲一些任务的时间(也意味着质量)了。按照什么标准牺牲?这个项目的战略!我们在第三节提到过的战略。
  我的经验是如果你什么都赶进度,其结果可能就是十件事情你一件也没做好,想想多么失败啊。所以,把资源投到你熟悉和有把握的事情上,最后的结果是十件事情,你有三件做成了精品,三件完成,还有四件因为某些原因延误,成绩单是否靓丽了很多呢?战略决定优先级,而正确排列事情的优先级是一个项目经理能力的主要体现。好,现在项目已经完成了前期工作,了解了项目的目标、搞清楚了手上的资源,制定了项目的策略,然后编制了项目的整体计划,项目进入实施阶段。进入这个阶段反而是项目经理比较空闲的时候,不像前期的时候项目经理要象记者一样到处和不同的人接触,搞清楚他们在说什么,努力猜测他们在想什么和他们的真正目的,那才是最累人的事情。当然,小项目的项目经理往往自己也是一个资源,要做很多事情,这时候反而比谁都苦。
  项目经理这段时间的主要工作是保持和客户领导以及自己领导的沟通。和客户领导沟通时特别要注意,除非你需要对方给你支持,那么你才需要讲得具体一点,否则,告诉他一切正常就可以了,而且态度要积极一些,千万不要说一些领导不懂的细节,比如:&王局长,最近项目进度还算正常,就是JVM经常发生一些内存泄漏的情况&&
— 熊爸爸 @ 9:14 am
IBM WebSphere 开发工具详解 &推荐
定价:33.00元
售价:26.10元 (79%)
【作者】廖荣贵 张钰汶 编著 李水根 等改编
【出版社】电子工业出版社
【出版日期】2004年01月
—————————————-WebSphere开发与管理
作者】涂传滨,邱丽娟编著
【出版社】电子工业出版社
【出版日期】2007年01月
【版别版次】2007年1月
—————————————-
— 熊爸爸 @ 3:28 pm
ウノウはサーバ構築、設計開発から運用まですべてプログラマが行うのですが、 以前100人以上が関わるプロジェクトの設計を主任でやらせていただいたことがありました。 開発規模が大きくなると、リクルーティングや開発効率の点から、このような体制になることも 多いかと思います。
設計者やプログラマ、運用者がすべて同じ会社の人間の場合の話なので、参考になるかは わかりませんがそのときに感じたことを書きたいと思います。
?一番大事なのはユースケース    大規模なサイトでは「設計上一番美しい設計が運営上最良ではない」ことが  多々あります。原因には「組織の力関係、歴史」や「運用者のITリテラシー」  など設計者一人では解決できない問題も多々あります。    用件の分析などをする場合は必ず、関わる人の職場を自分の目で見ること、  関わるひとと実際話してみることが大切だと思います。
 特に、新機能がリリースされる前には運用や開発の責任者に相談(根回し)を  しておいたほうがスムーズにリリースできることが多いです。
?仕様書は更新できる分だけ作り最新に保つ    「更新されない仕様書は悪」です。他のサイトからこちらのインターフェースを使用する際に、  更新されていない仕様書を参考にして作ってしまう可能性がありますが、こちらは  全く把握できません。
 仕様書は必要かつ自分が更新できる分だけ作成し、必ず更新日、更新者、更新履歴  をつけるようにし、 仕様が更新されるたびに最新の状態に保ち、プロジェクトの  MLなどで告知しましょう。
?設計者とプログラマの関係    設計書を実際のコードに起こすのはプログラマなのですが、プログラマと  設計者の間で、上流、下流という概念は捨てるべきだと思います。
 プログラマは設計者の大きな見方になりうる(唯一の?)存在で  レビューをすり抜けた設計書の穴を見つけてくれるのもプログラマであることが多いです。  実装レベルの話になると、プログラマのほうがよく知っていることも  多々ありますのでプログラマに対して謙虚に接して、設計に関してもよく話し合いましょう。
また経験豊富なプログ
— 熊爸爸 @ 12:55 pm
1C82--MAAX-50& 1C82--MAAX-29& 1C82--MAAX-50& 1C82--MAAX-64&
— 熊爸爸 @ 8:53 am
&C#锐利体验:创建完全可编辑的&DataGrid:在DataGrid中添加一个合计字段:大量.net学习资源:daab&3.1使用笔记:用DataGrid实现特殊需求:Subversion配置安装教程(一):Subversion配置安装教程(二):Subversion配置安装教程(三):最经典的实现字符数控制的方案哦!(完善版):编写高性能&Web&应用程序的&10&个技巧:Creating&a&Fully&Editable&DataGrid:判断一个string是否可以为数字:C#中使用XML&&实现DOM:C#中使用XML&&编写XML:C#中使用XML&&读取XML:几种调用WebService的方法:完整的在.net后台执行javascript脚本集合:创建跨多列、多行表头的DataGrid(补全版):Response.ContentType&控制输出文件类型:无刷新显示数据--xmlHttp的应用:JS特效40:ADO.NET学习笔记(一):ADO.NET学习笔记(二):ADO.NET学习笔记(三):利用GDI+函数构造图形报表:动态加载类(在程序中调用DLL文件):动态ItemTemplate的实现:An&Extensible&Master-Page&Framework&for&ASP.NET&1.1&Using&Pattern&Oriented&Design:ASP.NET跨应用程序进行登录的解决:身份验证和授权:
— 熊爸爸 @ 11:22 am
发掘.net性能对于一个application至关重要,所以现在经常找一些可以提高性能的技巧,下面是有关DataBinder的一个小技巧。对于一般的绑定,我们使用&%# DataBinder.Eval(Container.DataItem, &字段名&) %&用DataBinder.eval 绑定不必关心数据来源。不必关心数据的类型eval会把这个数据对象转换为一个字符串。在底层绑定做了很多工作,使用了反射性能。正因为使用方便了,但却影响了数据性能.来
看下&%# DataBinder.Eval(Container.DataItem, &字段名&)
%&。当于dataset绑定时DataItem其实是一个DataRowView(如果绑定的是一个数据读取器DataReader,它就是一个
IdataRecord。)因此直接转换成DataRowView的话,将会给性能带来很大提升 &%#
ctype(Container.DataItem,DataRowView).Row(&字段名&) %& 对数据的绑定建议使用&%#
ctype(Container.DataItem,DataRowView).Row(&字段名&) %&。数据量大的时候可提高几百倍的速度。使用时注意两方面:1.需在页面添加&%@ Import namespace=&System.Data&%&2.注意字段名的大小写(要特别注意)。如果和查询的不一致,在某些情况下会导致比&%# DataBinder.Eval(Container.DataItem, &字段名&) %&还要慢。如果想进一步提高速度,可采用&%# ctype(Container.DataItem,DataRowView).Row(0) %&的方法,不过其可读性不高。
— 熊爸爸 @ 5:40 pm
Asp.net的身份验证有有三种,分别是&Windows | Forms | Passport&,其中又以Forms验证用的最多,也最灵活。Forms
验证方式对基于用户的验证授权提供了很好的支持,可以通过一个登录页面验证用户的身份,将此用户的身份发回到客户端的Cookie,之后此用户再访问这个
web应用就会连同这个身份Cookie一起发送到服务端。服务端上的授权设置就可以根据不同目录对不同用户的访问授权进行控制了。
题来了,在实际是用中我们往往需要的是基于角色,或者说基于用户组的验证和授权。对一个网站来说,一般的验证授权的模式应该是这样的:根据实际需求把用户
分成不同的身份,就是角色,或者说是用户组,验证过程不但要验证这个用户本身的身份,还要验证它是属于哪个角色的。而访问授权是根据角色来设置的,某些角
色可以访问哪些资源,不可以访问哪些资源等等。要是基于用户来授权访问将会是个很不实际的做法,用户有很多,还可能随时的增减,不可能在配置文件中随时的
为不断增加的新用户去增加访问授权的。
下面大概的看一下Forms的过程。
Forms身份验证基本原理:
一 身份验证
要采用Forms身份验证,先要在应用程序根目录中的Web.config中做相应的设置:
&&&authentication mode=&Forms&&&&&&forms name=&.ASPXAUTH& loginUrl=&/Default.aspx& protection=&All& timeout=&30& path=&/& /&&&&/authentication&
其中&authentication mode= &forms&& 表示本应用程序采用Forms验证方式。1.
&forms&标签中的name表示指定要用于身份验证的 HTTP Cookie。默认情况下,name 的值是
.ASPXAUTH。采用此种方式验证用户后,以此用户的信息建立一个FormsAuthenticationTicket类型的身份验证票,再加密序列
化为一个字符串,最后将这个字符串写到客户端的name指定名字的Cookie中.一旦这个Cookie写到客户端后,此用户再次访问这个web应用时会
将连同Cookie一起发送到服务端,服务端将会知道此用户是已经验证过的.
再看一下身份验证票都包含哪些信息呢,我们看一下FormsAuthenticationTicket类:CookiePath: 返回发出 Cookie 的路径。注意,窗体的路径设置为 /。由于窗体区分大小写,这是为了防止站点中的 URL 的大小写不一致而采取的一种保护措施。这在刷新 Cookie 时使用Expiration: 获取 Cookie 过期的日期/时间。IsPersistent: 如果已发出持久的 Cookie,则返回 true。否则,身份验证 Cookie 将限制在浏览器生命周期范围内。IssueDate: 获取最初发出 Cookie 的日期/时间。Name: 获取与身份验证 Cookie 关联的用户名。UserData :获取存储在 Cookie 中的应用程序定义字符串。Version: 返回字节版本号供将来使用。
&forms&标签中的loginUrl指定如果没有找到任何有效的身份验证 Cookie,为登录将请求重定向到的 URL。默认值为
default.aspx。loginUrl指定的页面就是用来验证用户身份的,一般此页面提供用户输入用户名和密码,用户提交后由程序来根据自己的需要
来验证用户的合法性(大多情况是将用户输入信息同数据库中的用户表进行比较),如果验证用户有效,则生成同此用户对应的身份验证票,写到客户端的
Cookie,最后将浏览器重定向到用户初试请求的页面.一般是用FormsAuthentication.RedirectFromLoginPage
方法来完成生成身份验证票,写回客户端,浏览器重定向等一系列的动作.public static void RedirectFromLoginPage( string userName, bool createPersistentCookie, string strCookiePath );其中:userName: 就是此用户的标示,用来标志此用户的唯一标示,不一定要映射到用户账户名称.createPersistentCookie: 标示是否发出持久的 Cookie。若
不是持久Cookie,Cookie的有效期Expiration属性有当前时间加上web.config中timeout的时间,每次请求页面时,在验
证身份过程中,会判断是否过了有效期的一半,要是的话更新一次cookie的有效期;若是持久cookie,Expiration属性无意义,这时身份验
证票的有效期有cookie的Expires决定,RedirectFromLoginPage方法给Expires属性设定的是50年有效期。strCookiePath: 标示将生成的Cookie的写到客户端的路径,身份验证票中保存这个路径是在刷新身份验证票Cookie时使用(这也是生成Cookie的Path),若没有strCookiePath 参数,则使用web.config中 path属性的设置。这里可以看到,此方法参数只有三个,而身份验证票的属性有七个,不足的四个参数是这么来的:IssueDate: Cookie发出时间由当前时间得出,Expiration:过期时间由当前时间和下面要说的&forms&标签中timeout参数算出。此参数对非持久性cookie有意义。UserData: 这个属性可以用应用程序写入一些用户定义的数据,此方法没有用到这个属性,只是简单的将此属性置为空字符串,请注意此属性,在后面我们将要使用到这个属性。Version: 版本号由系统自动提供.RedirectFromLoginPage
方法生成生成身份验证票后,会调用FormsAuthentication.Encrypt
方法,将身份验证票加密为字符串,这个字符串将会是以.ASPXAUTH为名字的一个Cookie的值。这个Cookie的其它属性的生成:
Domain,Path属性为确省值,Expires视createPersistentCookie参数而定,若是持久cookie,Expires设
为50年以后过期;若是非持久cookie,Expires属性不设置。生成身份验证Cookie后,将此Cookie加入到Response.Cookies中,等待发送到客户端。最后RedirectFromLoginPage方法调用FormsAuthentication.GetRedirectUrl 方法获取到用户原先请求的页面,重定向到这个页面。
3. &forms&标签中的timeout和path,是提供了身份验证票写入到Cookie过期时间和默认路径。
以上就是基于Forms身份验证的过程,它完成了对用户身份的确认。下面介绍基于Forms身份验证的访问授权。
二 访问授权
证了身份,是要使用这个身份,根据不同的身份我们可以进行不同的操作,处理,最常见的就是对不同的身份进行不同的授权,Forms验证就提供这样的功能。
Forms授权是基于目录的,可以针对某个目录来设置访问权限,比如,这些用户可以访问这个目录,那些用户不能访问这个目录。同样,授权设置是在你要控制的那个目录下的web.config文件中来设置:&authorization&&&&&&allow users=&comma-separated list of users&&&&&&&&&roles=&comma-separated list of roles&&&&&&&&&verbs=&comma-separated list of verbs& /&&&&& &deny users=&comma-separated list of users&&&&&&&&&roles=&comma-separated list of roles&&&&&&&&&verbs=&comma-separated list of verbs& /&&/authorization&
&allow&标签表示允许访问,其中的属性1. users:一个逗号分隔的用户名列表,这些用户名已被授予对资源的访问权限。问号 (?) 允许匿名用户;星号 (*) 允许所有用户。2. roles:一个逗号分隔的角色列表,这些角色已被授予对资源的访问权限。3. verbs:一个逗号分隔的 HTTP 传输方法列表,这些 HTTP 传输方法已被授予对资源的访问权限。注册到 ASP.NET 的谓词为 GET、HEAD、POST 和 DEBUG。
&deny&标签表示不允许访问。其中的属性同上面的。
运行时,授权模块迭代通过 &allow& 和 &deny&
标记,直到它找到适合特定用户的第一个访问规则。然后,它根据找到的第一项访问规则是 &allow& 还是 &deny&
规则来允许或拒绝对 URL 资源的访问。Machine.config 文件中的默认身份验证规则是 &allow
users=&*&/&,因此除非另行配置,否则在默认情况下会允许访问。
那么这些user 和roles又是如何得到的呢?下面看一下授权的详细过程:
一旦一个用户访问这个网站,就行登录确认了身份,身份验证票的cookie也写到了客户端。之后,这个用户再次申请这个web的页面,身份验证票的
cookie就会发送到服务端。在服务端,asp.net为每一个http请求都分配一个HttpApplication对象来处理这个请求,在
HttpApplication.AuthenticateRequest事件后,安全模块已建立用户标识,就是此用户的身份在web端已经建立起来,这
个身份完全是由客户端发送回来的身份验证票的cookie建立的。2. 用户身份在HttpContext.User
属性中,在页面中可以通过Page.Context
来获取同这个页面相关的HttpContext对象。对于Forms验证,HttpContext.User属性是一个GenericPrincipal
类型的对象,GenericPrincipal只有一个公开的属性Identity,有个私有的m_role属性,是string[]类型,存放此用户是
属于哪些role的数组,还有一个公开的方法IsInRole(string role),来判断此用户是否属于某个角色。由于身份验证票的cookie中根本没有提供role这个属性,就是说Forms身份验证票没有提供此用户的role信息,所以,对于Forms验证,在服务端得到的GenericPrincipal 用户对象的m_role属性永远是空的。3.
GenericPrincipal. Identity
属性是一个FormsIdentity类型的对象,这个对象有个Name属性,就是此用户的标示,访问授权就是将此属性做为user来进行授权验证的。
FormsIdentity还有一个属性,就是Ticket属性,此属性是身份验证票FormsAuthenticationTicket类型,就是之前
服务器写到客户端的身份验证票。服务器在获取到身份验证票FormsAuthenticationTicket对象后,查看这个身份验证票是不是
非持久的身份验证,是的话要根据web.config中timeout属性设置的有效期来更新这个身份验证票的cookie(为避免危及性能,在经过了超
过一半的指定时间后更新该 Cookie。这可能导致精确性上的损失。持久性 Cookie 不超时。)4.
在HttpApplication.ResolveRequestCache事件之前,asp.net开始取得用户请求的页面,建立
HttpHandler控制点。这就意味着,在HttpApplication.ResolveRequestCache事件要对用户访问权限就行验证,
看此用户或角色是否有权限访问这个页面,之后在这个请求的生命周期内再改变此用户的身份或角色就没有意义了。
上是Forms验证的全过程,可以看出,这个Forms验证是基于用户的,没有为角色的验证提供直接支持。身份验证票
FormsAuthenticationTicket
中的Name属性是用户标示,其实还有一个属性UserData,这个属性可以由应用程序来写入自定义的一些数据,我们可以利用这个字段来存放role的
信息,从而达到基于角色验证的目的。
Forms身份验证基于角色的授权
一 身份验证
在web.config的&authentication&的设置还是一样:
&authentication mode=&forms&& &&&&&forms name=&.ASPXAUTH & loginUrl=&/login.aspx& timeout=&30& path= &/&&&&&&&/forms& &/authentication&
/login.aspx
验证用户合法性页面中,在验证了用户的合法性后,还要有个取得此用户属于哪些role的过程,这个看各个应用的本身如何设计的了,一般是在数据库中会有个
use_role表,可以从数据库中获得此用户属于哪些role,在此不深究如何去获取用户对应的role,最后肯定能够获得的此用户对应的所有的
role用逗号分割的一个字符串。在上面的非基于角色的方法中,我们用了
FormsAuthentication.RedirectFromLoginPage
方法来完成生成身份验证票,写回客户端,浏览器重定向等一系列的动作。这个方法会用一些确省的设置来完成一系列的动作,在基于角色的验证中我们不能用这一
个方法来实现,要分步的做,以便将一些定制的设置加进来:
1. 首先要根据用户标示,和用户属于的角色的字符串来创建身份验证票public FormsAuthenticationTicket(int version, //设为1string name, //用户标示DateTime issueDate, //Cookie 的发出时间, 设置为 DateTime.Now DateTime expiration, //过期时间bool isPersistent, //是否持久性(根据需要设置,若是设置为持久性,在发出cookie时,cookie的Expires设置一定要设置)string userData, //这里用上面准备好的用逗号分割的role字符串string cookiePath // 设为&/&,这要同发出cookie的路径一致,因为刷新cookie要用这个路径);
FormsAuthenticationTicket
Ticket = new FormsAuthenticationTicket (1,&kent&,DateTime.Now,
DateTime.Now.AddMinutes(30), false,UserRoles,&/&) ;
2. 生成身份验证票的Cookie2.1 将身份验证票加密序列化成一个字符串string HashTicket = FormsAuthentication.Encrypt (Ticket) ;2.2 生成cookieHttpCookie UserCookie = new HttpCookie(FormsAuthentication.FormsCookieName, HashTicket) ;FormsAuthentication.FormsCookieName 是用来获取web.config中设置的身份验证cookie的名字,缺省为& .ASPXAUTH&.若身份验证票中的isPersistent属性设置为持久类,则这个cookie的Expires属性一定要设置,这样这个cookie才会被做为持久cookie保存到客户端的cookie文件中.3. 将身份验证票Cookie输出到客户端通过Response.Cookies.Add(UserCookie) 将身份验证票Cookie附加到输出的cookie集合中,发送到客户端.4. 重定向到用户申请的初试页面.
验证部分代码(这部分代码是在login.aspx页面上点击了登录按钮事件处理代码):
private void Buttonlogin_Click(object sender, System.EventArgs e){&&&& string user = TextBoxUser.T //读取用户名&&&& string password = TextBoxPassword.T //读取密码&&&& if(Confirm(user,password) == true) //confirm方法用来验证用户合法性的&&&&{&&&&&&&& string userRoles = UserToRole(user); //调用UserToRole方法来获取role字符串&&&&&&&&
FormsAuthenticationTicket Ticket = new FormsAuthenticationTicket
(1,user,DateTime.Now, &&&&&&&& DateTime.Now.AddMinutes(30),
false,userRoles,&/&) ; //建立身份验证票对象&&&&&&&& string HashTicket = FormsAuthentication.Encrypt (Ticket) ; //加密序列化验证票为字符串&&&&&&&& HttpCookie UserCookie = new HttpCookie(FormsAuthentication.FormsCookieName, HashTicket) ; //生成Cookie&&&& &&&& Context.Response.Cookies.Add (UserCookie) ; //输出Cookie&&&&&&&& Context.Response.Redirect (Context.Request[&ReturnUrl&]) ; // 重定向到用户申请的初始页面&&&& }&&&&else&&&&{&&&&&&&&// 用户身份未被确认时的代码&&&&}}//此方法用来验证用户合法性的private bool Confirm(string user,string password){&&&&//相应的代码}//此方法用来获得的用户对应的所有的role用逗号分割的一个字符串private string UserToRole(string user){&&&&//相应的代码}
二 基于角色访问授权
这里我们要做的是,将客户端保存的身份验证票中UserData中保存的表示角色的信息恢复到在服务端表示用户身份的GenericPrincipal对象中(记住,原来的验证过程中, GenericPrincipal对象只包含了用户信息,没有包含role信息)一个Http请求的过程中,HttpApplication.AuthenticateRequest事件表示安全模块已建立用户标识,就是此用户的身份在web端已经建立起来, 在这个事件之后我们就可以获取用户身份信息了.在HttpApplication.ResolveRequestCache
事件之前,asp.net开始取得用户请求的页面,建立HttpHandler控制点,这时就已经要验证用户的权限了,所以恢复用户角色的工作只能在
HttpApplication.AuthenticateRequest事件和
HttpApplication.ResolveRequestCache事件之间的过程中做.我们选择Application_AuthorizeRequest事件中做这个工作,可以在global.asax文件中处理HttpApplication的所有的事件,代码如下:
protected void Application_AuthorizeRequest(object sender, System.EventArgs e){&&&&HttpApplication App = (HttpApplication)&&&& HttpContext Ctx = App.C //获取本次Http请求相关的HttpContext对象&&&&if (Ctx.Request.IsAuthenticated == true) //验证过的用户才进行role的处理&&&&{&&&&&&&&FormsIdentity Id = (FormsIdentity)Ctx.User.I&&&&&&&&FormsAuthenticationTicket Ticket = Id.T //取得身份验证票&&&&&&&&string[] Roles = Ticket.UserData.Split (‘,’) ; //将身份验证票中的role数据转成字符串数组&&&&&&&&Ctx.User = new GenericPrincipal (Id, Roles) ; //将原有的Identity加上角色信息新建一个GenericPrincipal表示当前用户,这样当前用户就拥有了role信息&&&&}}
— 熊爸爸 @ 5:35 pm
1. 打开新的窗口并传送参数:   传送参数:response.write(&<script>window.open('*.aspx?id=&+this.DropDownList1.SelectIndex+&&id1=&+...+&')</script>&)  接收参数:string a = Request.QueryString(&id&);string b = Request.QueryString(&id1&);  2.为按钮添加对话框Button1.Attributes.Add(&onclick&,&return confirm('确认?')&);button.attributes.add(&onclick&,&if(confirm('are you sure...?')){}else{}&)  3.删除表格选定记录int intEmpID = (int)MyDataGrid.DataKeys[e.Item.ItemIndex];string deleteCmd = &DELETE from Employee where emp_id = & + intEmpID.ToString()  4.删除表格记录警告private void DataGrid_ItemCreated(Object sender,DataGridItemEventArgs e){ switch(e.Item.ItemType) {  case ListItemType.Item :  case ListItemType.AlternatingItem :  case ListItemType.EditItem:   TableCell myTableC   myTableCell = e.Item.Cells[14];   LinkButton myDeleteB   myDeleteButton = (LinkButton)myTableCell.Controls[0];   myDeleteButton.Attributes.Add(&onclick&,&return confirm('您是否确定要删除这条信息');&);     default:    }}  5.点击表格行链接另一页private void grdCustomer_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e){ //点击表格打开 if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)  e.Item.Attributes.Add(&onclick&,&window.open('Default.aspx?id=& + e.Item.Cells[0].Text + &');&);}  双击表格连接到另一页  在itemDataBind事件中if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem){ string OrderItemID =e.item.cells[1].T ... e.item.Attributes.Add(&ondblclick&, &location.href='../ShippedGrid.aspx?id=& + OrderItemID + &'&);}  双击表格打开新一页if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem){ string OrderItemID =e.item.cells[1].T ... e.item.Attributes.Add(&ondblclick&, &open('../ShippedGrid.aspx?id=& + OrderItemID + &')&);}6.表格超连接列传递参数<asp:HyperLinkColumn Target=&_blank& headertext=&ID号& DataTextField=&id& NavigateUrl=&aaa.aspx?id=' <%# DataBinder.Eval(Container.DataItem, &数据字段1&)%>' & name='<%# DataBinder.Eval(Container.DataItem, &数据字段2&)%>' />  7.表格点击改变颜色if (e.Item.ItemType == ListItemType.Item ||e.Item.ItemType == ListItemType.AlternatingItem){ e.Item.Attributes.Add(&onclick&,&this.style.backgroundColor='#99cc00';    this.style.color='buttontext';this.style.cursor='default';&);}   写在DataGrid的_ItemDataBound里if (e.Item.ItemType == ListItemType.Item ||e.Item.ItemType == ListItemType.AlternatingItem){e.Item.Attributes.Add(&onmouseover&,&this.style.backgroundColor='#99cc00';   this.style.color='buttontext';this.style.cursor='default';&);e.Item.Attributes.Add(&onmouseout&,&this.style.backgroundColor='';this.style.color='';&);}  8.关于日期格式  日期格式设定DataFormatString=&{0:yyyy-MM-dd}&  我觉得应该在itembound事件中e.items.cell[&你的列&].text=DateTime.Parse(e.items.cell[&你的列&].text.ToString(&yyyy-MM-dd&))  9.获取错误信息并到指定页面  不要使用Response.Redirect,而应该使用Server.Transfer  e.g// in global.asaxprotected void Application_Error(Object sender, EventArgs e) {if (Server.GetLastError() is HttpUnhandledException)Server.Transfer(&MyErrorPage.aspx&);//其余的非HttpUnhandledException异常交给ASP.NET自己处理就okay了
}  Redirect会导致post-back的产生从而丢失了错误信息,所以页面导向应该直接在服务器端执行,这样就可以在错误处理页面得到出错信息并进行相应的处理   10.清空CookieCookie.Expires=[DateTime];Response.Cookies(&UserName&).Expires = 0  11.自定义异常处理//自定义异常处理类 using Susing System.Dnamespace MyAppException{ /// <summary> /// 从系统异常类ApplicationException继承的应用程序异常处理类。 /// 自动将异常内容记录到Windows NT/2000的应用程序日志 /// </summary> public class AppException:System.ApplicationException {  public AppException()  {   if (ApplicationConfiguration.EventLogEnabled)LogEvent(&出现一个未知错误。&);  } public AppException(string message) {  LogEvent(message); } public AppException(string message,Exception innerException) {  LogEvent(message);  if (innerException != null)  {   LogEvent(innerException.Message);  } } //日志记录类 using S using System.C using System.D using System.IO; using System.T using System.T namespace MyEventLog {  /// <summary>  /// 事件日志记录类,提供事件日志记录支持   /// <remarks>  /// 定义了4个日志记录方法 (error, warning, info, trace)   /// </remarks>  /// </summary>  public class ApplicationLog  {   /// <summary>   /// 将错误信息记录到Win2000/NT事件日志中   /// <param name=&message&>需要记录的文本信息</param>   /// </summary>   public static void WriteError(String message)   {    WriteLog(TraceLevel.Error, message);   }   /// <summary>   /// 将警告信息记录到Win2000/NT事件日志中   /// <param name=&message&>需要记录的文本信息</param>   /// </summary>   public static void WriteWarning(String message)   {    WriteLog(TraceLevel.Warning, message);     }   /// <summary>   /// 将提示信息记录到Win2000/NT事件日志中   /// <param name=&message&>需要记录的文本信息</param>   /// </summary>   public static void WriteInfo(String message)   {    , message);   }   /// <summary>   /// 将跟踪信息记录到Win2000/NT事件日志中   /// <param name=&message&>需要记录的文本信息</param>   /// </summary>   public static void WriteTrace(String message)   {    WriteLog(TraceLevel.Verbose, message);   }   /// <summary>   /// 格式化记录到事件日志的文本信息格式   /// <param name=&ex&>需要格式化的异常对象</param>   /// <param name=&catchInfo&>异常信息标题字符串.</param>   /// <retvalue>   /// <para>格式后的异常信息字符串,包括异常内容和跟踪堆栈.</para>   /// </retvalue>   /// </summary>   public static String FormatException(Exception ex, String catchInfo)   {    StringBuilder strBuilder = new StringBuilder();    if (catchInfo != String.Empty)    {     strBuilder.Append(catchInfo).Append(&\r\n&);    }    strBuilder.Append(ex.Message).Append(&\r\n&).Append(ex.StackTrace);    return strBuilder.ToString();   }   /// <summary>   /// 实际事件日志写入方法   /// <param name=&level&>要记录信息的级别(error,warning,info,trace).</param>   /// <param name=&messageText&>要记录的文本.</param>   /// </summary>   private static void WriteLog(TraceLevel level, String messageText)   {    try    {      EventLogEntryType LogEntryT     switch (level)     {      case TraceLevel.Error:       LogEntryType = EventLogEntryType.E             case TraceLevel.Warning:       LogEntryType = EventLogEntryType.W             :       LogEntryType =             case TraceLevel.Verbose:       LogEntryType = EventLogEntryType.SuccessA             default:       LogEntryType = EventLogEntryType.SuccessA            } 
    EventLog eventLog = new EventLog(&Application&,
ApplicationConfiguration.EventLogMachineName,
ApplicationConfiguration.EventLogSourceName );     //写入事件日志     eventLog.WriteEntry(messageText, LogEntryType);    }   catch {} //忽略任何异常  }  } //class ApplicationLog}12.Panel 横向滚动,纵向自动扩展&asp:panel style=&overflow-x:overflow-y:&&&/asp:panel&  13.回车转换成Tab &script language=&javascript& for=&document& event=&onkeydown&& if(event.keyCode==13
&& event.srcElement.type!='button' &&
event.srcElement.type!='submit' &&
    event.srcElement.type!='reset' &&
event.srcElement.type!=''&& event.srcElement.type!='textarea');
   event.keyCode=9;&/script&onkeydown=&if(event.keyCode==13) event.keyCode=9&  14.DataGrid超级连接列DataNavigateUrlField=&字段名& DataNavigateUrlFormatString=&http://xx/inc/delete.aspx?ID={0}&  15.DataGrid行随鼠标变色private void DGzf_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e){ if (e.Item.ItemType!=ListItemType.Header) {  e.Item.Attributes.Add( &onmouseout&,&this.style.backgroundColor=\&&+e.Item.Style[&BACKGROUND-COLOR&]+&\&&);  e.Item.Attributes.Add( &onmouseover&,&this.style.backgroundColor=\&&+ &#EFF3F7&+&\&&); }}  16.模板列&ASP:TEMPLATECOLUMN visible=&False& sortexpression=&demo& headertext=&ID&&&ITEMTEMPLATE&&ASP:LABEL
text='&%# DataBinder.Eval(Container.DataItem, &ArticleID&)%&'
runat=&server& width=&80%& id=&lblColumn& /&&/ITEMTEMPLATE&&/ASP:TEMPLATECOLUMN&&ASP:TEMPLATECOLUMN headertext=&选中&&&HEADERSTYLE wrap=&False& horizontalalign=&Center&&&/HEADERSTYLE&&ITEMTEMPLATE&&ASP:CHECKBOX id=&chkExport& runat=&server& /&&/ITEMTEMPLATE&&EDITITEMTEMPLATE&&ASP:CHECKBOX id=&chkExportON& runat=&server& enabled=&true& /&&/EDITITEMTEMPLATE&&/ASP:TEMPLATECOLUMN&  后台代码protected void CheckAll_CheckedChanged(object sender, System.EventArgs e){ //改变列的选定,实现全选或全不选。 CheckBox chkE if( CheckAll.Checked) {  foreach(DataGridItem oDataGridItem in MyDataGrid.Items)  {   chkExport = (CheckBox)oDataGridItem.FindControl(&chkExport&);   chkExport.Checked =  } } else {  foreach(DataGridItem oDataGridItem in MyDataGrid.Items)  {   chkExport = (CheckBox)oDataGridItem.FindControl(&chkExport&);   chkExport.Checked =  } }}  17.数字格式化  【&%#Container.DataItem(&price&)%&的结果是500.0000,怎样格式化为500.00?】&%#Container.DataItem(&price&,&{0:¥#,##0.00}&)%&int i=123456;string s=i.ToString(&###,###.00&); 18.日期格式化  【aspx页面内:&%# DataBinder.Eval(Container.DataItem,&Company_Ureg_Date&)%&  显示为:
19:44:28  我只想要: 】&%# DataBinder.Eval(Container.DataItem,&Company_Ureg_Date&,&{0:yyyy-M-d}&)%&  应该如何改?  【格式化日期】  取出来,一般是object((DateTime)objectFromDB).ToString(&yyyy-MM-dd&);  【日期的验证表达式】  A.以下正确的输入格式: [], [ 10:29:39 pm], [] ^((\d{2}(([0])|([13579][26]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))))|(\d{2}(([09])|([189]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\s(((0?[1-9])|(1[0-2]))\:([0-5][0-9])((\s)|(\:([0-5][0-9])\s))([AM|PM|am|pm]{2,2})))?$  B.以下正确的输入格式:[], [], [] ^\d{4}[\-\/\s]?((((0[13578])|(1[02]))[\-\/\s]?(([0-2][0-9])|(3[01])))|(((0[469])|(11))[\-\/\s]?(([0-2][0-9])|(30)))|(02[\-\/\s]?[0-2][0-9]))$
  【大小写转换】HttpUtility.HtmlEncode(string);HttpUtility.HtmlDecode(string)  19.如何设定全局变量  Global.asax中  Application_Start()事件中  添加Application[属性名] =  就是你的全局变量  20.怎样作到HyperLinkColumn生成的连接后,点击连接,打开新窗口?  HyperLinkColumn有个属性Target,将器值设置成&_blank&即可.(Target=&_blank&)  【ASPNETMENU】点击菜单项弹出新窗口  在你的menuData.xml文件的菜单项中加入URLTarget=&_blank&,如:&?xml version=&1.0& encoding=&GB2312&?&&MenuData ImagesBaseURL=&images/&& &MenuGroup&&MenuItem Label=&内参信息& URL=&Infomation.aspx& &&MenuGroup ID=&BBC&&&MenuItem Label=&公告信息& URL=&Infomation.aspx& URLTarget=&_blank& LeftIcon=&file.gif&/&&MenuItem Label=&编制信息简报& URL=&NewInfo.aspx& LeftIcon=&file.gif& /&......  最好将你的aspnetmenu升级到1.2版  21.读取DataGrid控件TextBox值foreach(DataGrid dgi in yourDataGrid.Items){ TextBox tb = (TextBox)dgi.FindControl(&yourTextBoxId&); tb.Text....}  23.在DataGrid中有3个模板列包含Textbox分别为 DG_ShuLiang (数量) DG_DanJian(单价) DG_JinE(金额)分别在5.6.7列,要求在录入数量及单价的时候自动算出金额即:数量*单价=金额还要求录入时限制为 数值型.我如何用客户端脚本实现这个功能?  〖思归〗&asp:TemplateColumn HeaderText=&数量&& &ItemTemplate&&asp:TextBox id=&ShuLiang& runat='server' Text='&%# DataBinder.Eval(Container.DataItem,&DG_ShuLiang&)%&' onkeyup=&javascript:DoCal()&/&&asp:RegularExpressionValidator
id=&revS& runat=&server& ControlToValidate=&ShuLiang&
ErrorMessage=&must be integer& ValidationExpression=&^\d+$& /&&/ItemTemplate&&/asp:TemplateColumn&&asp:TemplateColumn HeaderText=&单价&& &ItemTemplate&&asp:TextBox id=&DanJian& runat='server' Text='&%# DataBinder.Eval(Container.DataItem,&DG_DanJian&)%&' onkeyup=&javascript:DoCal()&/&&asp:RegularExpressionValidator
id=&revS2& runat=&server& ControlToValidate=&DanJian&
ErrorMessage=&must be numeric& ValidationExpression=&^\d+(\.\d*)?$&
/&&/ItemTemplate&&/asp:TemplateColumn&&asp:TemplateColumn HeaderText=&金额&& &ItemTemplate&&asp:TextBox id=&JinE& runat='server' Text='&%# DataBinder.Eval(Container.DataItem,&DG_JinE&)%&' /&&/ItemTemplate&&/asp:TemplateColumn&&script language=&javascript&&function DoCal(){ var e = event.srcE var row = e.parentNode.parentN var txts = row.all.tags(&INPUT&); if (!txts.length || txts.length & 3)   var q = txts[txts.length-3]. var p = txts[txts.length-2]. if (isNaN(q) || isNaN(p))   q = parseInt(q); p = parseFloat(p); txts[txts.length-1].value = (q * p).toFixed(2);}&/script&4.datagrid选定比较底下的行时,为什么总是刷新一下,然后就滚动到了最上面,刚才选定的行因屏幕的关系就看不到了。page_load page.smartNavigation=true  25.在Datagrid中修改数据,当点击编辑键时,数据出现在文本框中,怎么控制文本框的大小 ? private void DataGrid1_ItemDataBound(obj sender,DataGridItemEventArgs e){ for(int i=0;i&e.Item.Cells.Count-1;i++)  if(e.Item.ItemType==ListItemType.EditType)  {   e.Item.Cells[i].Attributes.Add(&Width&, &80px&)  } }  26.对话框private static string ScriptBegin = &&script language=\&JavaScript\&&&;private static string ScriptEnd = &&/script&&;public static void ConfirmMessageBox(string PageTarget,string Content){ string ConfirmContent=&var retValue=window.confirm('&+Content+&');&+&if(retValue){window.location='&+PageTarget+&';}&; ConfirmContent=ScriptBegin + ConfirmContent + ScriptE Page ParameterPage = (Page)System.Web.HttpContext.Current.H ParameterPage.RegisterStartupScript(&confirm&,ConfirmContent); //Response.Write(strScript);}  27. 将时间格式化:string aa=DateTime.Now.ToString(&yyyy年MM月dd日&);   1.1 取当前年月日时分秒 currentTime=System.DateTime.N  1.2 取当前年 int 年= DateTime.Now.Y  1.3 取当前月 int 月= DateTime.Now.M   1.4 取当前日 int 日= DateTime.Now.D   1.5 取当前时 int 时= DateTime.Now.H   1.6 取当前分 int 分= DateTime.Now.M   1.7 取当前秒 int 秒= DateTime.Now.S   1.8 取当前毫秒 int 毫秒= DateTime.Now.M   28.自定义分页代码:  先定义变量 :public static int pageC //总页面数 public static int curPageIndex=1; //当前页面   下一页: if(DataGrid1.CurrentPageIndex & (DataGrid1.PageCount - 1)) {  DataGrid1.CurrentPageIndex += 1;  curPageIndex+=1; } bind(); // DataGrid1数据绑定函数   上一页: if(DataGrid1.CurrentPageIndex &0) {  DataGrid1.CurrentPageIndex += 1;  curPageIndex-=1; } bind(); // DataGrid1数据绑定函数   直接页面跳转: int a=int.Parse(JumpPage.Value.Trim());//JumpPage.Value.Trim()为跳转值 if(a&DataGrid1.PageCount) {  this.DataGrid1.CurrentPageIndex=a; } bind();29.DataGrid使用:   添加删除确认: private void DataGrid1_ItemCreated(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e) {  foreach(DataGridItem di in this.DataGrid1.Items)  {   if(di.ItemType==ListItemType.Item||di.ItemType==ListItemType.AlternatingItem)   {    ((LinkButton)di.Cells[8].Controls[0]).Attributes.Add(&onclick&,&return confirm('确认删除此项吗?');&);   }  } }   样式交替: ListItemType itemType = e.Item.ItemT if (itemType == ListItemType.Item ) {  e.Item.Attributes[&onmouseout&] = &javascript:this.style.backgroundColor='#FFFFFF';&;  e.Item.Attributes[&onmouseover&] = &javascript:this.style.backgroundColor='#d9ece1';cursor='hand';& ; } else if( itemType == ListItemType.AlternatingItem) {  e.Item.Attributes[&onmouseout&] = &javascript:this.style.backgroundColor='#a0d7c4';&;  e.Item.Attributes[&onmouseover&] = &javascript:this.style.backgroundColor='#d9ece1';cursor='hand';& ; }   添加一个编号列: DataTable dt= c.ExecuteRtnTableForAccess(sqltxt); //执行sql返回的DataTable DataColumn dc=dt.Columns.Add(&number&,System.Type.GetType(&System.String&)); for(int i=0;i&dt.Rows.Ci++) {  dt.Rows[i][&number&]=(i+1).ToString(); } DataGrid1.DataSource= DataGrid1.DataBind();   DataGrid1中添加一个CheckBox,页面中添加一个全选框 private void CheckBox2_CheckedChanged(object sender, System.EventArgs e) {  foreach(DataGridItem thisitem in DataGrid1.Items)  {   ((CheckBox)thisitem.Cells[0].Controls[1]).Checked=CheckBox2.C  } }   将当前页面中DataGrid1显示的数据全部删除 foreach(DataGridItem thisitem in DataGrid1.Items) {  if(((CheckBox)thisitem.Cells[0].Controls[1]).Checked)  {   string strloginid= DataGrid1.DataKeys[thisitem.ItemIndex].ToString();   Del (strloginid); //删除函数  } }   30.当文件在不同目录下,需要获取数据库连接字符串(如果连接字符串放在Web.config,然后在Global.asax中初始化)   在Application_Start中添加以下代码: Application[&ConnStr&]=this.Context.Request.PhysicalApplicationPath+ConfigurationSettings.   AppSettings[&ConnStr&].ToString();  31. 变量.ToString()   字符型转换 转为字符串 12345.ToString(&n&); //生成 12,345.00 12345.ToString(&C&); //生成 ¥12,345.00 12345.ToString(&e&); //生成 1.4 12345.ToString(&f4&); //生成
12345.ToString(&x&); //生成 3039 (16进制) 12345.ToString(&p&); //生成 1,234,500.00%   32、变量.Substring(参数1,参数2);   截取字串的一部分,参数1为左起始位数,参数2为截取几位。 如:string s1 = str.Substring(0,2);   33.在自己的网站上登陆其他网站:(如果你的页面是通过嵌套方式的话,因为一个页面只能有一个FORM,这时可以导向另外一个页面再提交登陆信息) &SCRIPT language=&javascript&& &!--  function gook(pws)  {   frm.submit();  } //--& &/SCRIPT& &body leftMargin=&0& topMargin=&0& onload=&javascript:gook()& marginwidth=&0& marginheight=&0&& &form name=&frm& action=& http://220.194.55.68:6080/login.php?retid=7259 & method=&post&& &tr& &td&&input id=&f_user& type=&hidden& size=&1& name=&f_user& runat=&server&&&input id=&f_domain& type=&hidden& size=&1& name=&f_domain& runat=&server&&&input class=&box& id=&f_pass& type=&hidden& size=&1& name=&pwshow& runat=&server&& &INPUT id=&lng& type=&hidden& maxLength=&20& size=&1& value=&5& name=&lng&&&INPUT id=&tem& type=&hidden& size=&1& value=&2& name=&tem&& &/td& &/tr& &/form&   文本框的名称必须是你要登陆的网页上的名称,如果源码不行可以用vsniffer 看看。   下面是获取用户输入的登陆信息的代码:
name=Request.QueryString[&EmailName&]; try {  int a=name.IndexOf(&@&,0,name.Length);  f_user.Value=name.Substring(0,a);  f_domain.Value=name.Substring(a+1,name.Length-(a+1));  f_pass.Value=Request.QueryString[&Psw&]; } catch {  Script.Alert(&错误的邮箱!&);  Server.Transfer(&index.aspx&); }
— 熊爸爸 @ 5:33 pm
任何编程模型都有常见的性能缺陷,ASP.NET 也不例外。本节描述一些可避免在代码中出现性能瓶颈的方法。
在未使用时禁用会话状态:
并非所有的应用程序或页都要求基于每个用户的会话状态。如果不需要,可将其完全禁用。这可以通过以下页级别指令轻松实现:
&%@ Page EnableSessionState=&false& %&
注意:如果页需要访问会话变量但不创建或修改它们,请将指令值设置为 ReadOnly。还可为 XML Web 服务方法禁用会话状态。请参阅 XML Web 服务一节中的。
慎重选择会话状态提供程序:
ASP.NET 为存储应用程序的会话数据提供了三种不同的方法:进程内会话状态、作为 Windows 服务的进程外会话状态和 SQL
数据库中的进程外会话状态。每种方法都有自己的优点,但进程内会话状态是迄今为止速度最快的解决方案。如果仅在会话状态中存储少量易失数据,则应使用进程
内提供程序。进程外解决方案主要用于 Web 花园和 Web 农场方案,或用于当服务器/进程重新启动时不能丢失数据的情况。
避免与服务器间的过多往返行程:Web 窗体页框架是 ASP.NET 的最佳功能之一,因为它可以显著减少为完成某项任务所需编写的代码量。使用服务器控件和回发事件处理模型的页元素编程访问无疑是最省时的功能。但是,对这些功能的使用存在着适当和不适当的方法,了解何时使用它们是适当的很重要。
应用程序通常仅在检索数据或存储数据时才需要往返于服务器。多数数据操作可在往返行程间在客户端进行。例如在用户提交数据前,通常可以在客户端验证窗体项。通常,如果不需要将信息中继回服务器,则不应往返于服务器。
如果编写自己的服务器控件,请考虑让它们为上级(支持 ECMAScript)浏览器呈现客户端代码。通过采用&智能&控件,可显著减少对 Web 服务器的不必要点击次数。
使用 Page.IsPostback 避免往返行程上的额外工作:如果处理服务器控件回发,通常需要在第一次请求页时执行代码,该代码不同于激发事件时用于往返行程的代码。如果检查 Page.IsPostBack 属性,则代码可按条件执行,具体取决于是否有对页的初始请求或对服务器控件事件的响应。这样做似乎很明显,但实际上可以忽略此项检查而不更改页的行为。例如:
&script language=&VB& runat=&server&&
Public ds As DataSet
Sub Page_Load(sender As Object, e As EventArgs)
' ...set up a connection and command here...
If Not (Page.IsPostBack)
Dim query As String = &select * from Authors where FirstName like '%JUSTIN%'&
myCommand.Fill(ds, &Authors&)
myDataGrid.DataBind()
Sub Button_Click(sender As Object, e As EventArgs)
Dim query As String = &select * from Authors where FirstName like '%BRAD%'&
myCommand.Fill(ds, &Authors&)
myDataGrid.DataBind()
End Sub&/script&&form runat=&server&&
&asp:datagrid datasource='&%# ds.Tables[&Authors&].DefaultView %&' runat=&server&/&&br&
&asp:button onclick=&Button_Click& runat=&server&/&&/form&
Page_Load 事件对所有请求都执行,因此检查了 Page.IsPostBack,以便在处理 Button_Click 事件回发时不执行第一个查询。请注意,即使没有此检查,页的行为也不会改变,因为第一个查询中的绑定会被事件处理程序中的 DataBind 调用推翻。记住,在编写页时会很容易忽略这个简单的性能改进。
谨慎适当地使用服务器控件:尽管服务器控件使用起来非常容易,但它并不总是最佳选择。许多情况下,简单的呈现或数据绑定替换可以完成同样的事情。例如:
&script language=&VB& runat=&server&&
Public imagePath As String
Sub Page_Load(sender As Object, e As EventArgs)
'...retrieve data for imagePath here...
DataBind()
End Sub&/script&&%--the span and img server controls are unecessary...--%&The path to the image is: &span innerhtml='&%# imagePath %&' runat=&server&/&&br&&img src='&%# imagePath %&' runat=&server&/&&br&&br&&%-- use databinding to substitute literals instead...--%&The path to the image is: &%# imagePath %&&br&&img src='&%# imagePath %&' /&&br&&br&&%-- or a simple rendering expression...--%&The path to the image is: &%= imagePath %&&br&&img src='&%= imagePath %&' /&
在此示例中,不需要服务器控件将值代入发送回客户端的结果 HTML。在许多其他情况下此方法同样适用,甚至在服务器控件模板中。但是,如果要以编程方式操作控件属性、从中处理事件或利用其状态保存,则服务器控件更合适。应检查服务器控件的使用,并查找可优化的代码。
避免过多的服务器控件视图状态:自动状态管理是一种功能,它使服务器控件能够在往返行程中重新填充它们的值,而不要求编写任何代码。但是,此功能并不能任意使用,因为控件状态是在隐藏的窗体字段中传入和传出服务器的。应当明白 ViewState 何时有帮助,何时没有。例如,如果在每个往返行程中将控件绑定到数据(如第四条提示中的数据网格示例所示),则不要求控件维护它的视图状态,因为无论如何都将擦除任何重新填充的数据。
默认情况下,为所有的服务器控件启用 ViewState。若要禁用它,请将控件的 EnableViewState 属性设置为 false,如下例所示:
&asp:datagrid EnableViewState=&false& datasource=&...& runat=&server&/&
还可在页级别关闭 ViewState。这在根本不从页回发时非常有用,如下例所示:
&%@ Page EnableViewState=&false& %&
注意,User Control 指令也支持此属性。若要分析页上的服务器控件使用的视图状态量,请启用跟踪并查看&控件层次结构&表中的&视图状态&列。有关跟踪功能及如何启用它的更多信息,请参阅功能。
对字符串连接使用 Response.Write:在页面或用户控件中对字符串连接使用 HttpResponse.Write 方法。该方法提供非常有效的缓冲和连接服务。但是,如果您打算执行大量的连接,则使用下列示例中的方法(即多次调用 Response.Write)来连接字符串比仅调用一次 Response.Write 方法要快。
Response.Write(&a&)Response.Write(myString)Response.Write(&b&)Response.Write(myObj.ToString())Response.Write(&c&)Response.Write(myString2)Response.Write(&d&)
不要依赖代码中的异常:异常非常浪费资源,应在代码中尽量避免。绝不要将异常作为控制常规程序流的方法。如果可
以在代码中检测到会导致异常的条件,就应该那样做,而不要等到捕捉异常后再处理该条件。常见的方案包括:检查空值,分配给将分析为数字值的字符串,或在应
用数学运算前检查特定值。例如:
' Consider changing this:Try
result = 100 / numCatch (e As Exception)
result = 0End Try// To this:If Not (num = 0)
result = 100 / numElse
result = 0End If
在 Visual Basic 或 JScript 代码中使用早期绑定:Visual
Basic、VBScript 和 JScript
的优点之一是它们无类型的特性。只需使用它们即可创建变量,并不需要显式的类型声明。从一种类型分配到另一种类型时,同样会自动执行转换。这既是优点也是
缺点,因为就性能而言,晚期绑定虽很方便但很昂贵。
Visual Basic 语言现在通过使用特殊的 Option Strict 编译器指令来支持类型安全编程。为了向后兼容,默认情况下 ASP.NET 不启用 Option Strict。但为了获得最佳性能,应在页上使用 Strict 属性或使用 Control 指令,为页启用 Option Strict:
&%@ Page Language=&VB& Strict=&true& %&&%Dim BDim C As String' This causes a compiler error:A = &Hello&' This causes a compiler error:B = &World&' This does not:C = &!!!!!!&' But this does:C = 0%&
JScript 也支持无类型编程,但它不提供强制早期绑定的编译器指令。满足以下条件的变量是后期绑定的:
被显式声明为对象。
是无类型声明的类的字段。
是无显式类型声明的专用函数/方法成员,并且无法从其使用推断出类型。
最后一个特点非常复杂。如果 JScript 编译器能够根据使用变量的方式推断出其类型就会进行优化。在下面的示例中,变量 A 为早期绑定,而变量 B 为后期绑定:
var A;var B;A = &Hello&;B = &World&;B = 0;
为获得最佳性能,请将 JScript 变量声明为具有类型。例如,&var A : String&。
将大量调用的 COM 组件移植为托管代码:.NET 框架一种非常容易的方法与传统的 COM
组件相互操作。其优点是可以在保留现有代码的同时利用新的平台。但是,在某些情况下,保留旧组件的性能成本超出了将组件迁移到托管代码的费用。每种情况都
非常特别,而决定所需更改的内容的最佳方法是测量站点的性能。但是,通常 COM
交互性的性能影响与函数调用的次数或从非托管代码封送到托管代码的数据量成比例。由于各层间的通讯数,需要同大量调用交互的组件称为&chatty&。应
考虑将这种组件移植为完全托管的代码,以从 .NET 平台提供的性能收益中获益。或者可以考虑重新设计组件,以请求更少的调用或一次封送更多数据。
将 SQL 存储过程用于数据访问:在 .NET 框架提供的所有数据访问方法中,基于 SQL
的数据访问是生成性能最好的可缩放 Web 应用程序的最佳选择。使用托管 SQL
提供程序时,可通过使用编译的存储过程而不是特殊查询,获得额外的性能提高。有关使用 SQL 存储过程的示例,请参考本教程的一节。
使用 SqlDataReader 获得快进只读数据游标:SqlDataReader 对象对从 SQL 数据库中检索的数据提供前进只读游标。如果 SqlDataReader 适合于您的情况,则它是一个比 DataSet 更好的选择。因为 SqlDataReader 支持 IEnumerable 接口,甚至还可以绑定服务器控件。有关使用 SqlDataReader 的示例,请参阅本教程的一节。
尽可能缓存数据和输出:ASP.NET
编程模型提供了一个简单的机制,在不需要为每个请求动态计算页输出或数据时缓存它们。在设计页时可以考虑用缓存来优化应用程序中那些预期有最大通信量的地
方。适当地使用缓存可增强站点的性能,有时甚至可以增大一个数量级或更多,这是 .NET
框架的任何其他功能无法企及的。有关如何使用缓存的更多信息,请参阅本教程的一节。
为多处理器计算机启用 Web 花园:ASP.NET 进程模型帮助在多处理器计算机上启用可缩放性,将工作分发给多个进程(每个 CPU 一个),并且每个进程都将处理器关系设置为其 CPU。该技术称为 Web 园艺,它可以显著提高某些应用程序的性能。若要了解如何启用 Web 园艺,请参考一节。
不要忘记禁用调试模式:ASP.NET 配置中的 &compilation& 节控制应用程序是否在调试模式中编译。调试模式严重降低性能。在部署生产应用程序或测量性能之前,始终记住禁用调试模式。有关调试模式的更多信息,请参考题为 的章节。
— 熊爸爸 @ 4:23 pm
 现在从对ASP.NET页面的执行顺序开始,体会一下B/S结构的程序的特点,下图是ASP.NET页面的执行顺序说明:  Page_Init(页面初始化引发的事件)&&&Page_Load(加载页面时引发的事件)&&&Control&& Event(服务器控件引发的事件)&&&Page_UnLoad(页面从内存中卸载时引发的事件)  Page_Init和Page_UnLoad不常用,但是这里还是要说明一下。Page_Init和Page_Load事件区别在于,只有后者才能完全加载控件,绑定数据,虽然你可以在Page_Init中访问控件,但是其viewstate都不会被加载,所以此时控件中只拥有默认值。  这里说到了viewstate,我们先来做一个大致的了解&&其实在ASP.NET中有两个viewstate。一个是控件本身的,用来维护控件自己的一些状态,比如说某个空间有变色的功能,它的viewstate就维护这个功能,这个viewstate是不能被用户访问的。相信自己写过控件的朋友都会有这样的感觉,自己写控件当然也要用自己的一个viewstate来维护这个控件的状态;而另外一个viewstate,是用户使用的,这个 viewstate和Session几乎一模一样,必须要先对其进行定义,才能使用。  每当点击ASP.NET的Web网页上的 Button、LinkButton或ImageButton等控件时,表单就会被发送到服务器上。如果某些控件的AutoPostBack属性被设置为 true,那么当该控件的状态被改变后,也会使表单会发送回服务器。?(AutoPostBack属性,它只有两个bool值,true/false。如果这个属性被设置成false,那么点击后就不会立刻将变化传给服务器处理,也就不会有该控件的SelectedIndexChanged事件。)  每次当表单被发送回服务器,就会被重新加载,启动Page_Load事件,执行Page_Load事件处理程序中的所有代码(注意,是每次都会执行!)。很显然把网页的初始化代码放在这里是最合适不过。我们经常会希望在每次加载网页时执行一些代码,如一些控件的数据绑定。  当我们希望只有在网页第一次加载时执行另一些代码(基本上都是数据的默认绑定),甚至希望一些代码在除首次加载外的每次加载时执行。那么我们可以利用 IsPostBack特性来完成这一功能。在网页第一次加载时,该属性的值是false。如果网页因回送而被重新加载,IsPostBack属性的值就会被设置为true。  在ASP.NET应用程序中,如果需要在页面第一次显示时执行一些初始化操作,必须判断IsPostBack属性!  在 ASP.NET使用Page.IsPostback,那么就可以避免往返行程上的额外工作:如果处理服务器控件回发,通常需要在第一次请求页时执行代码,该代码不同于激发事件时用于往返行程的代码。如果检查?Page.IsPostBack?属性,则代码可按条件执行,具体取决于是否有对页的初始请求或对服务器控件事件的响应。这样做似乎很明显,但实际上可以忽略此项检查而不更改页的行为。该属性用的好坏,直接关系到你程序运行是否按照你最初的意愿,也关系到整个页面的效率。因为,如果每次都会给控件绑定数据,不管你是第一次访问,还是提交了数据以后,那么这个页面程序的效率可想而知。  一个B/S结构的页面每一次提交,它都会重新从头到尾执行一次。而C/S结构的程序就不会这样,这是和C/S结构的程序最大的区别!其实,得不到控件的数据,都是因为这个原因。
— 熊爸爸 @ 3:30 pm
如果你是有关互联网的从业者、创业者或爱好者,只要你有自己个性化的理解和偏见,不论长短、不论高低,都欢迎参与我们每天一次的【】!我们的选题范围一般为互联网上的最新热点、最快动向和最酷产品。在这里,你我都是业界的审视者、批评者和建构者。
查看当天“业内人说”,请上;参与当天“业内人说”,请私信 。
データベース
推荐的网址(BLOG)
推荐的网址(技术)
推荐的网址(非技术)

我要回帖

更多关于 泰坦之旅 开启隐藏 的文章

 

随机推荐