2012年8月2日星期四

ASP.NET编程中你也应该知道的那些事

ASP.NET编程中你也应该知道的那些事

首先说一下我的上一篇文章:这些年、我收集的JQuery代码,由于刚接触Live Writer不久,不是很熟悉,看到园友们反馈的错误,不想误导大家,就在浏览器中直接修改了,可能是由于代码段是VSPaste粘贴的缘故,保存后导致排版乱掉了。我是一个追求完美的人,不愿意看到那样参差不齐的代码,更不愿意让园友们看到。于是就决定删除重新发布。现在已经重新发布了,可能还是会有写问题是我没有察觉到的,欢迎大家指出。。。还有我发现博客园的随笔不能编辑权限,比如发布了一篇随笔,但是后来我不想让别人看到这篇随笔了,怎么办?现在好像只能删除,要是能设置不公开就好了,好像博客园现在还没这功能吧?还是我没发现?希望“园长”可以考虑一下眨眼,好了 不说废话了进入今天的主题。

 

1、跟踪页面执行

设置断点是页面调试过程中的常用手段,除此之外,还可以通过查看页面的跟踪信息进行错误排查以及性能优化。

asp.net中启用页面跟踪非常方便,只需在Page指令中加入Trace="True"属性即可:

<%@ Page Language="C#" Trace="true" %>
   跟踪信息可以分为两类:
a.页面执行详细情况
  
其中主要包括页面生命周期中各事件列表、控件树列表(可以查看每个控件的HTML字节数以及ViewState字节数)、Session状态、Application状态、Cookie集合、QueryString集合、服务器变量等信息。
 
  
b.自定义跟踪信息
通过在页面代码中调用Trace.Write()或Trace.Warn()方法便可将指定内容写入跟踪信息中的"Trace Information"节。就算页面发生了错误,跟踪信息还是会显示出来,并且在发布应用程序时无需删除相关的跟踪代码,只需从Page指令中移除Trace属性即可。

2、在服务器端控件中添加客户端属性

我们有时会向服务器端控件中添加一些特殊的属性,这类属性不需要服务器端的处理,只需简单的发送至客户端即可,我们不妨称其为客户端属性,例如HTML属性或自定义属性(可能用于实现某种特定的JavaScript功能)。可以通过以下几种方法达到这个目的

 

a.直接向控件添加客户端属性

        <asp:Button ID="MyButton" Text="ClickMe" onmouseover="this.style.cursor='pointer'" 
        runat="server" />
其中的onmouseover是客户端属性,注意,编译器是允许这种写法的,但会显示警告。使用是正常的。
 
  
b.调用内置方法
可以通过调用WebControl.Attributes.Add()方法为控件添加客户端属性,如下所示
         MyButton.Attributes.Add("onmouseover", "this.style.cursor='pointer'");
 
  
c.使用OnClientClick
asp.net 2.0以后为按钮控件(包括Button、LinkButton、ImageButton控件)提供了OnClientClick属性,可以这样写
         MyButton.OnClientClick = "alert('Hello!')";
3、表单数据的服务器端验证

将数据验证任务从服务器端迁移到客户端的过程促使了JavaScript的产生,这也是我们沿用至今的一种方式。但只有在保证客户端JavaScript正常运行的前提下,这种方式才能发挥其作用。不幸的是,总有一些例外,比如浏览器不支持JavaScript,或者用户刻意关闭了浏览器的JavaScript功能,这就导致了第一重防护失效。比较保险的做法是加入第二重防护,即对用户提交的数据进行服务器端验证,但这无疑将增加开发者的工作量。

asp.net 2.0提供了一系列表单数据验证控件,可以非常轻松的完成客户端及服务器端的双重数据验证任务。但要使服务器端验证功能发挥作用,还需要用到Page.IsValid属性,请看下面的例子

    <form id="MyForm" runat="server">    <div>        Username:<asp:TextBox ID="txtName" runat="server"></asp:TextBox>        <asp:RequiredFieldValidator ID="RequiredFieldValidator1" ControlToValidate="txtName" 
        ErrorMessage="input ur name" Display="Dynamic" runat="server">
        </asp:RequiredFieldValidator>    </div>    <div>        <asp:Button ID="btnSubmit" Text="submit" runat="server" />    </div>    </form>
这是一个HTML片段,其中有一个RequiredFieldValidator控件用于检查是否已填写姓名。下面是点击按钮时执行的服务器端代码:
        protected void btnSubmit_Click(object sender, EventArgs e)        {            if (Page.IsValid) //注意:不要遗漏对Page.IsValid属性的判断                {                Response.Write("你的名字是:" + txtName.Text);            }        }
其中,要特别注意对Page.IsValid属性的判断,只有页面中所有验证控件对数据的验证都成功时,Page.IsValid属性才为True,这代表提交的数据为有效数据,可以进入下一步操作。
4、跳过表单验证

在某些情况下,我们需要跳过表单中所有控件的验证,然而在另外一些情况下,我们却希望有选择的触发表单中某些控件的验证功能。分别来看看这两种情况:

 

a.跳过所有验证

假设有个表单,其中除了各种数据录入控件外还有两个按钮,一个是提交按钮,另一个是取消按钮,同时表单中还有一些数据验证控件。我们希望当点击取消按钮的时候无需验证表单中数据的有效性,而是直接将页面提交至服务器并将其重定向到某个指定页面。

要实现这个功能,可以利用按钮控件(包括Button、LinkButton、ImageButton控件)的CausesValidation属性,将该属性设为false即可跳过表单中的所有验证。

 

b.触发某些验证

假设有个表单,被划分成两个功能区,一个用于用户登录,另一个用于用户注册,我们希望当点击登录按钮时只触发登录区的数据验证,当点击注册按钮时只触发注册区的数据验证。

解决办法是将相关的数据验证控件和数据提交控件(按钮控件)加入同一个验证组,这一点是通过将各相关控件的ValidationGroup属性设为相同的值来实现的。

5、保持滚动条位置

假设有个页面,其中以列表形式显示了一些数据记录,每次编辑其中的记录时都需要向服务器提交页面,为了提供良好的用户体验,我们希望每次编辑一条记录并保存后,滚动条位置都能保持不变。传统的做法是每次提交页面时将当前滚动条所在位置信息按某种方式(Hidden字段或QueryString)传给服务器端,当页面返回客户端时,由服务器端根据传入的位置信息以JavaScript形式重新设置滚动条位置。

如果通过asp.net来实现这一功能将变得非常简单,只需在Page指令中加入MaintainScrollPositionOnPostback="true"属性即可:

<%@ Page Language="C#" MaintainScrollPositionOnPostback="true">%>
6、禁用不必要的ViewState

在asp.net的运行机制中,ViewState起着重要的作用。ViewState经过编码后存入表单Hidden字段,每当页面回传至服务器时再进行解码。因此,ViewState的使用会带来两个问题:带宽的占用以及计算资源的消耗。好在不是所有控件都需要启用ViewState,我们完全可以禁用不必要的ViewState。

ViewState默认是开启的,需要手动关闭:

 

a.禁用页面ViewState

在Page指令中加入EnableViewState="false"属性即可:

<%@ Page Language="C#" EnableViewState="false">%>
加入这个属性后,整个页面以及其中的所有控件都将无法使用ViewState,因此需谨慎使用
 

b.禁用控件ViewState

这是推荐的方式,将控件的EnableViewState属性设为False即可禁用其ViewState,这里有个简单的窍门:

如果某个控件的状态不能由操作者改变,则可以禁用其ViewState。最典型的莫过于Label控件了,只能显示信息,无法操作。

但TextBox、DorpDownList等控件的状态是可以改变的(通过输入、选择等操作),因此保留他们的ViewState还是有用的。

 7、一些提高运行速度的小技巧

1)避免使用ArrayList,因为对象要转化为System.Object加入ArrayList,取出时又要转化为想要的类型,设计到大量的装箱拆箱过程,推荐使用自定义集合取代ArrayList,.net还在System.Collection.Specialized命名空间下为string提供了一个强类型的集合类StringCollection

2)用Hashtable 取代其他字典类型,如:StringDictionary, NameValueCollection, HybridCollection。

3)经常为字符串声明常量来封装他们

            //避免            MyClass obj = new MyClass();            obj.name = "name";            //推荐                const string c_name = "name";            MyClass obj = new MyClass();            obj.name = c_name;

4)使用String.Compare取代将两个字符串转化为uppercase或lowercase再来比较他们

            const string C_VALUE = "COMPARE";            if (String.Compare(sVariable, C_VALUE, true) == 0)                Console.Write("SAME");
5)避免使用+操作符来连接字符串,而使用StringBuilder来连接
 
            //避免            String s"<parent>";            s"<child>";            s"Data";            s"</child>";            s"</parent>";                          //推荐            StringBuilder sbnew StringBuilder();            sb"<parent>");            sb"<child>");            sb"Data");            sb"</child>");            sb"</parent>");
6)对于只读
            //避免            new ();            "/packet/child").InnerText;            //推荐            XPathDocument new XPathDocument(new StringReader(oContext.Value));            XPathNavigator xnav = XPathNodeIterator xpNodeIter = xnav.Select("packet/child");            iCount = xpNodeIter.Count;            xpNodeIter = xnav.SelectDescendants(XPathNodeType.Element, false);            while (xpNodeIter.MoveNext())                sCurrValues += xpNodeIter.Current.Value + "~";
7)避免在循环体类声明并初始化对象,而应该在循环体外声明,在循环体类初始化!
            //避免            for (int i = 0; i < 10; i++)                MyClass objSC = new MyClass();            //推荐            MyClass objSC = null;            for (int i = 0; i < 10; i++)                objSC = new MyClass();
我觉得应尽量少用服务器端控件,一般情况下用服务器端(runat=server)控件会使性能损失30-50%左右(没有测试过,数据来源于网络吐舌鬼脸
文章的内容很浅,对于园子里的大牛们可能没有什么帮助,但是我觉得像我们这样的小菜鸟还是获益良多的。资源整理自网络。
 

TAG: