ASP.NET页面开发有哪些关键要点?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1816个文字,预计阅读时间需要8分钟。
Page,每个ASP.NET开发人员都应该比较熟悉。本次博客我将算术专家专题谈谈它。不过,我不会算术说,在Page中使用控件的一些话题,也不会说Page的生命周期的相关话题。因为...
Page,我想每个ASP.NET开发人员对它应该都是比较熟悉的。
这次的博客我就打算专门谈谈它。
不过呢,我不打算说 在Page中使用控件的一些话题,也不会说Page的生命周期的相关话题,
因为我认为这些话题被人谈论的次数实在是太多了,尤其是市面上的ASP.NET的书籍,都会比较喜欢这些话题。
我不喜欢重复,因此今天我只想谈些人家不谈的那点事,但我认为它们仍然很重要。
一些重要的Page指令虽然Page公开了很多属性,让我们可以在运行时调整它的状态与行为,但是,还有些重要的参数却是以“指令”方式提供的,需要在设计时就指定。
下面是我整理的一些我认为 比较重要并且经常需要使用 的指令:
注意:如果需要开发一个异步页,必须要设置这个指令属性,以便在编译页面时实现IHttpAsyncHandler接口。 AsyncTimeOut定义在处理异步任务时使用的超时时间间隔(以秒为单位)。默认值为 45 秒。 该值必须是整数。
此属性仅对Page.RegisterAsyncTask()方法有效。 AutoEventWireup指示页的事件是否自动绑定。如果启用了事件自动绑定,则为 true;否则为 false。默认值为 true。
所谓的事件自动绑定就是识别Page_Load这些类型的页面事件处理程序。
事件自动绑定发生在页面第一次请求时,在后续请求中会使用缓存的委托调用列表,因此对性能的轻微影响也仅发生在第一次请求时。 EnableSessionState定义页的会话状态要求。如果启用了会话状态,则为 true;如果可以读取会话状态但不能进行更改,则为 ReadOnly;否则为 false。默认值为 true。
建议不要保留默认值:
1. 如果只是部分页面需要使用Session,那么不需要使用Session的页面请显式设置为关闭状态,
2. 对于不需要修改Session的页面请设置为ReadOnly。
页面编译时就是根据这个指令来决定生成对IRequiresSessionState,IReadOnlySessionState接口的实现关系。 EnableViewState指示是否在页请求之间保持视图状态。如果要保持视图状态,则为 true;否则为 false。默认值为 true。
强烈建议不要使用视图状态,因为它解决的问题比引用的问题更多。 MasterPageFile设置内容页的母版页或嵌套母版页的路径。支持相对路径和绝对路径。
可以在页面的PreInit事件中动态设置同名的属性实现动态切换母版页的功能。 Trace指示是否启用跟踪。如果启用了跟踪,则为 true;否则为 false。默认值为 false。
启用跟踪对页面调试非常有用,我们可以调用Page.Trace对象的方法输出一些有价值的诊断信息。
Page.Trace.Write()采用默认字体输出,Page.Trace.Warn()采用红色字体输出。
如果你总是记不住页面生命周期,启用跟踪后,一切就摆在你眼前。 ValidateRequest指示是否应发生请求验证。如果为true,请求验证将根据具有潜在危险的值的硬编码列表检查所有输入数据。默认值为 true。
如果希望用户输入HTML代码,请设置为false 。
注意:在ASP.NET 2.0中不验证ashx请求,但是ASP.NET 4.0默认会验证,
如果希望在4.0中兼容2.0的行为,请在web.config中配置<www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html } [SubmitMethod(AutoRedirect = true)] public void CustomizeLogin() { // 省略登录处理代码。 // 如果需要知道这段代码可以浏览下面的网址: // www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html }
注意观察,这二个C#方法的名称与页面二个submit按钮的name属性相同,因此可以猜测到这二个C#方法可以处理那二个submit按钮的提交请求。 那么这二段代码是如何运行起来的呢?有些人或许看到了[SubmitMethod]的使用,认为与它们有关。 其实这种说法并不正确,我也可以完全不使用它们。请记住:Attribute永远只是一个标记,它不可能让代码自动运行起来。
前面的代码能运行起来,与App_Browsers目录下的Page.browser文件有关,此文件的代码如下:
<browsers> <browser refID="Default"> <controlAdapters> <adapter controlType="System.Web.UI.Page" adapterType="FishDemoCodeLib.MyPageAdapter, FishDemoCodeLib" /> </controlAdapters> </browser> </browsers>
这里定义了一个MyPageAdapter,它用于Page控件的请求过程。
refID="Default" 表示是对ASP.NET定义的Default.browser文件补充一些配置,它将能匹配来自所有浏览器的请求。
我再来看一下MyPageAdapter的代码:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class SubmitMethodAttribute : Attribute { public bool AutoRedirect { get; set; } } internal sealed class MethodInvokeInfo { public MethodInfo MethodInfo; public SubmitMethodAttribute MethodAttribute; } public class MyPageAdapter : System.Web.UI.Adapters.PageAdapter { private static readonly Hashtable s_table = Hashtable.Synchronized(new Hashtable()); private static MethodInvokeInfo[] GetMethodInfo(Type type) { MethodInvokeInfo[] array = s_table[type.AssemblyQualifiedName] as MethodInvokeInfo[]; if( array == null ) { array = (from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Public) let a = m.GetCustomAttributes( typeof(SubmitMethodAttribute), false) as SubmitMethodAttribute[] where a.Length > 0 select new MethodInvokeInfo { MethodInfo = m, MethodAttribute = a[0] }).ToArray(); s_table[type.AssemblyQualifiedName] = array; } return array; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); if( Page.Request.Form.AllKeys.Length == 0 ) return; // 没有提交表单 MethodInvokeInfo[] array = GetMethodInfo(Page.GetType().BaseType); if( array.Length == 0 ) return; foreach( MethodInvokeInfo m in array ) { if( string.IsNullOrEmpty(Page.Request.Form[m.MethodInfo.Name]) == false ) { m.MethodInfo.Invoke(Page, null); if( m.MethodAttribute.AutoRedirect && Page.Response.IsRequestBeingRedirected == false ) Page.Response.Redirect(Page.Request.RawUrl); return; } } } }
这段代码并不长,核心代码更是比较少。
代码中,最重要的一块是MyPageAdapter的实现,它继承了System.Web.UI.Adapters.PageAdapter,
并重写了OnLoad方法(相当是在重写Page的OnLoad方法),也正是由于这个重写,
代码才有机会在页面的生命周期中被执行,这一点是HttpModule做不到的。
在OnLoad方法中做了以下事情:
1. 检查是不是发生了表单提交的操作。
2. 获取当前页面类型的所有[SubmitMethod]修饰过的方法。
3. 检查提交的表单数据中,是否存在与name对应的C#方法名。
4. 如果找到一个匹配的方法名,则调用。
5. 如果在[SubmitMethod]中设置了AutoRedirect=true,则引发重定向。
注意:如果不调用base.OnLoad(e); 那么页面的Load事件根本不会发生。
也就是说:PageAdapter.OnLoad的调用时间要早于Page.Onload方法。
由于这段代码仅供我写示例代码时使用,因此并没有检查要调用的方法的参数是否满足条件,也没有优化刻意去优化它的性能。 在我的设计中,被调用的方法应该是无参的,因此是容易判断的,而且可以使用一个固定签名的委托去优化它的,这些细节留着以后再去完善它吧!
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的按钮。
如果,您希望更容易地发现我的新博客,不妨点击一下右下角的。
因为,我的写作热情也离不开您的肯定支持。
感谢您的阅读,如果您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是Fish Li 。
本文共计1816个文字,预计阅读时间需要8分钟。
Page,每个ASP.NET开发人员都应该比较熟悉。本次博客我将算术专家专题谈谈它。不过,我不会算术说,在Page中使用控件的一些话题,也不会说Page的生命周期的相关话题。因为...
Page,我想每个ASP.NET开发人员对它应该都是比较熟悉的。
这次的博客我就打算专门谈谈它。
不过呢,我不打算说 在Page中使用控件的一些话题,也不会说Page的生命周期的相关话题,
因为我认为这些话题被人谈论的次数实在是太多了,尤其是市面上的ASP.NET的书籍,都会比较喜欢这些话题。
我不喜欢重复,因此今天我只想谈些人家不谈的那点事,但我认为它们仍然很重要。
一些重要的Page指令虽然Page公开了很多属性,让我们可以在运行时调整它的状态与行为,但是,还有些重要的参数却是以“指令”方式提供的,需要在设计时就指定。
下面是我整理的一些我认为 比较重要并且经常需要使用 的指令:
注意:如果需要开发一个异步页,必须要设置这个指令属性,以便在编译页面时实现IHttpAsyncHandler接口。 AsyncTimeOut定义在处理异步任务时使用的超时时间间隔(以秒为单位)。默认值为 45 秒。 该值必须是整数。
此属性仅对Page.RegisterAsyncTask()方法有效。 AutoEventWireup指示页的事件是否自动绑定。如果启用了事件自动绑定,则为 true;否则为 false。默认值为 true。
所谓的事件自动绑定就是识别Page_Load这些类型的页面事件处理程序。
事件自动绑定发生在页面第一次请求时,在后续请求中会使用缓存的委托调用列表,因此对性能的轻微影响也仅发生在第一次请求时。 EnableSessionState定义页的会话状态要求。如果启用了会话状态,则为 true;如果可以读取会话状态但不能进行更改,则为 ReadOnly;否则为 false。默认值为 true。
建议不要保留默认值:
1. 如果只是部分页面需要使用Session,那么不需要使用Session的页面请显式设置为关闭状态,
2. 对于不需要修改Session的页面请设置为ReadOnly。
页面编译时就是根据这个指令来决定生成对IRequiresSessionState,IReadOnlySessionState接口的实现关系。 EnableViewState指示是否在页请求之间保持视图状态。如果要保持视图状态,则为 true;否则为 false。默认值为 true。
强烈建议不要使用视图状态,因为它解决的问题比引用的问题更多。 MasterPageFile设置内容页的母版页或嵌套母版页的路径。支持相对路径和绝对路径。
可以在页面的PreInit事件中动态设置同名的属性实现动态切换母版页的功能。 Trace指示是否启用跟踪。如果启用了跟踪,则为 true;否则为 false。默认值为 false。
启用跟踪对页面调试非常有用,我们可以调用Page.Trace对象的方法输出一些有价值的诊断信息。
Page.Trace.Write()采用默认字体输出,Page.Trace.Warn()采用红色字体输出。
如果你总是记不住页面生命周期,启用跟踪后,一切就摆在你眼前。 ValidateRequest指示是否应发生请求验证。如果为true,请求验证将根据具有潜在危险的值的硬编码列表检查所有输入数据。默认值为 true。
如果希望用户输入HTML代码,请设置为false 。
注意:在ASP.NET 2.0中不验证ashx请求,但是ASP.NET 4.0默认会验证,
如果希望在4.0中兼容2.0的行为,请在web.config中配置<www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html } [SubmitMethod(AutoRedirect = true)] public void CustomizeLogin() { // 省略登录处理代码。 // 如果需要知道这段代码可以浏览下面的网址: // www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html }
注意观察,这二个C#方法的名称与页面二个submit按钮的name属性相同,因此可以猜测到这二个C#方法可以处理那二个submit按钮的提交请求。 那么这二段代码是如何运行起来的呢?有些人或许看到了[SubmitMethod]的使用,认为与它们有关。 其实这种说法并不正确,我也可以完全不使用它们。请记住:Attribute永远只是一个标记,它不可能让代码自动运行起来。
前面的代码能运行起来,与App_Browsers目录下的Page.browser文件有关,此文件的代码如下:
<browsers> <browser refID="Default"> <controlAdapters> <adapter controlType="System.Web.UI.Page" adapterType="FishDemoCodeLib.MyPageAdapter, FishDemoCodeLib" /> </controlAdapters> </browser> </browsers>
这里定义了一个MyPageAdapter,它用于Page控件的请求过程。
refID="Default" 表示是对ASP.NET定义的Default.browser文件补充一些配置,它将能匹配来自所有浏览器的请求。
我再来看一下MyPageAdapter的代码:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class SubmitMethodAttribute : Attribute { public bool AutoRedirect { get; set; } } internal sealed class MethodInvokeInfo { public MethodInfo MethodInfo; public SubmitMethodAttribute MethodAttribute; } public class MyPageAdapter : System.Web.UI.Adapters.PageAdapter { private static readonly Hashtable s_table = Hashtable.Synchronized(new Hashtable()); private static MethodInvokeInfo[] GetMethodInfo(Type type) { MethodInvokeInfo[] array = s_table[type.AssemblyQualifiedName] as MethodInvokeInfo[]; if( array == null ) { array = (from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Public) let a = m.GetCustomAttributes( typeof(SubmitMethodAttribute), false) as SubmitMethodAttribute[] where a.Length > 0 select new MethodInvokeInfo { MethodInfo = m, MethodAttribute = a[0] }).ToArray(); s_table[type.AssemblyQualifiedName] = array; } return array; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); if( Page.Request.Form.AllKeys.Length == 0 ) return; // 没有提交表单 MethodInvokeInfo[] array = GetMethodInfo(Page.GetType().BaseType); if( array.Length == 0 ) return; foreach( MethodInvokeInfo m in array ) { if( string.IsNullOrEmpty(Page.Request.Form[m.MethodInfo.Name]) == false ) { m.MethodInfo.Invoke(Page, null); if( m.MethodAttribute.AutoRedirect && Page.Response.IsRequestBeingRedirected == false ) Page.Response.Redirect(Page.Request.RawUrl); return; } } } }
这段代码并不长,核心代码更是比较少。
代码中,最重要的一块是MyPageAdapter的实现,它继承了System.Web.UI.Adapters.PageAdapter,
并重写了OnLoad方法(相当是在重写Page的OnLoad方法),也正是由于这个重写,
代码才有机会在页面的生命周期中被执行,这一点是HttpModule做不到的。
在OnLoad方法中做了以下事情:
1. 检查是不是发生了表单提交的操作。
2. 获取当前页面类型的所有[SubmitMethod]修饰过的方法。
3. 检查提交的表单数据中,是否存在与name对应的C#方法名。
4. 如果找到一个匹配的方法名,则调用。
5. 如果在[SubmitMethod]中设置了AutoRedirect=true,则引发重定向。
注意:如果不调用base.OnLoad(e); 那么页面的Load事件根本不会发生。
也就是说:PageAdapter.OnLoad的调用时间要早于Page.Onload方法。
由于这段代码仅供我写示例代码时使用,因此并没有检查要调用的方法的参数是否满足条件,也没有优化刻意去优化它的性能。 在我的设计中,被调用的方法应该是无参的,因此是容易判断的,而且可以使用一个固定签名的委托去优化它的,这些细节留着以后再去完善它吧!
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的按钮。
如果,您希望更容易地发现我的新博客,不妨点击一下右下角的。
因为,我的写作热情也离不开您的肯定支持。
感谢您的阅读,如果您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是Fish Li 。

