避免10 个常见ASP.NET缺陷 使网站平稳运行
LoadControl and Output Caching
LoadControl 和输出缓存
Rare is the ASP.NET application that doesn’t employ user controls. Before the advent of Master Pages, developers employed user controls to factor out common content, such as headers and footers. Even in ASP.NET 2.0, user controls provide an effective means for encapsulating content and behavior, and for dividing pages into regions whose ability to be cached can be controlled independently of the page as a whole—a special form of output caching known as fragment caching.
极少有不使用用户控件的 ASP.NET 应用程序。在出现母版页之前,开发人员使用用户控件来提取公用内容,如页眉和页脚。即使在 ASP.NET 2.0 中,用户控件也提供了有效的方法来封装内容和行为以及将页面分为多个区域,这些区域的缓存能力可以独立于作为整体的页面进行控制(一种称为段缓存的特殊输出缓存形式)。
User controls can be loaded declaratively or imperatively. Imperative loading relies on Page.LoadControl, which instantiates a user control and returns a Control reference. If the user control contains custom type members (for example, public properties), then you can cast that reference and access the custom members from your code. The user control in Figure 1 implements a property named BackColor. The following code loads the user control and assigns a value to BackColor:
用户控件可以采用声明的方式加载,也可以强制加载。强制加载依赖于 Page.LoadControl,它实例化用户控件并返回控件引用。如果用户控件包含自定义类型的成员(例如,公共属性),则您可以转换该引用并从您的代码访问自定义成员。图1 中的用户控件实现名为 BackColor 的属性。以下代码加载用户控件并向 BackColor 分配一个值:
protected void Page_Load(object sender, EventArgs e){// 加载用户控件并将其添加到页面中Control control = LoadControl("~/MyUserControl.ascx");PlaceHolder1.Controls.Add(control);// 设置其背景色((MyUserControl)control).BackColor = Color.Yellow;}
This code, simple as it is, is a trap waiting to ensnare the unwary developer. Can you identify the flaw?
以上代码实际上很简单,但却是一个等待粗心的开发人员掉进去的陷阱。您能找出其中的破绽吗?
If you guessed that the problem is related to output caching, you are correct. These code samples compile and run fine as shown, but try adding the following (perfectly legal) statement to MyUserControl.ascx:
如果您猜到该问题与输出缓存有关,那么您是正确的。正如您所看到的一样,上述代码示例编译和运行都正常,但是如果尝试将以下语句(完全合法)添加到 MyUserControl.ascx 中:
<%@ OutputCache Duration="5" VaryByParam="None" %>
Next time you run the page, you’ll be greeted by an InvalidCastException (oh joy!) accompanied by the following error message:
则当您下一次运行该页面时,您将看到 InvalidCastException (oh joy!) 和以下错误消息:
"Unable to cast object of type ‘System.Web.UI.PartialCachingControl’ to type ‘MyUserControl’."
“无法将类型为‘System.Web.UI.PartialCachingControl’的对象转换为类型‘MyUserControl’。”
So, here’s code that works great without an OutputCache directive, but bombs when an OutputCache directive is added. ASP.NET isn’t supposed to work this way. Pages (and controls) are supposed to be agnostic towards output caching. So what gives?
因此,此代码在没有 OutputCache 指令时运行正常,但如果添加了 OutputCache 指令就会出错。ASP.NET 不应该以这种方式运行。页面(和控件)对于输出缓存应该是不可知的。那么,这代表什么意思?
The problem is that when output caching is enabled for a user control, LoadControl no longer returns a reference to an instance of the control; instead, it returns a reference to an instance of PartialCachingControl that might or might not wrap a control instance, depending on whether the control’s output is cached. Consequently, developers who call LoadControl to load a user control dynamically and who also cast the control reference in order to access control-specific methods and properties must take care in how they do it in order for the code to work with or without an OutputCache directive.
问题在于为用户控件启用输出缓存时,LoadControl 不再返回对控件实例的引用;相反,它返回对 PartialCachingControl 实例的引用,而 PartialCachingControl 可能会也可能不会包装控件实例,具体取决于控件的输出是否被缓存。因此,如果开发人员调用 LoadControl 以动态加载用户控件并且为了访问控件特定的方法和属性而转换控件引用,他们必须注意进行该操作的方式,以便不管是否具有 OutputCache 指令,代码都可以运行。
Figure 2 demonstrates the proper way to load user controls dynamically and cast the returned control references. Here’s a synopsis of how it works:
图2 说明动态加载用户控件以及转换返回的控件引用的正确方法。以下是其工作原理概要:
- If the ASCX file lacks an OutputCache directive, LoadControl returns a MyUserControl reference. Page_Load casts the reference to MyUserControl and sets the control’s BackColor property.
- If the ASCX file includes an OutputCache directive and the control’s output isn’t cached, LoadControl returns a reference to a PartialCachingControl whose CachedControl property contains a reference to the underlying MyUserControl. Page_Load casts PartialCachingControl.CachedControl to MyUserControl and sets the control’s BackColor property.
- If the ASCX file includes an OutputCache directive and the control’s output is cached, LoadControl returns a reference to a PartialCachingControl whose CachedControl property is null. Seeing this, Page_Load does nothing more. It’s powerless to set the control’s BackColor property because the control’s output is delivered from the output cache. In other words, there is no MyUserControl on which to set a property.
The code in Figure 2 will work with or without an OutputCache directive in the .ascx file. It’s not pretty, but it averts nasty surprises. Simpler doesn’t always equate to more maintainable.
| • |
如果 ASCX 文件缺少 OutputCache 指令,则 LoadControl 返回一个 MyUserControl 引用。Page_Load 将该引用转换为 MyUserControl 并设置控件的 BackColor 属性。 |
| • |
如果 ASCX 文件包括一个 OutputCache 指令并且控件的输出没有被缓存,则 LoadControl 返回一个对 PartialCachingControl 的引用,此 PartialCachingControl 的 CachedControl 属性包含对基础 MyUserControl 的引用。Page_Load 将 PartialCachingControl.CachedControl 转换为 MyUserControl 并设置该控件的 BackColor 属性。 |
| • |
如果 ASCX 文件包括一个 OutputCache 指令并且控件的输出被缓存,则 LoadControl 返回一个对 PartialCachingControl(其 CachedControl 属性为空)的引用。注意,Page_Load 不再继续执行操作。无法设置控件的 BackColor 属性,因为该控件的输出来源于输出缓存。换句话说,根本没有要设置属性的 MyUserControl。 |
不管 .ascx 文件中是否具有 OutputCache 指令,图2 中的代码都将运行。虽然看起来复杂一点,但它会避免烦人的错误。简单并不总是代表易于维护。
from:asp学习网/title:避免10 个常见ASP.NET缺陷 使网站平稳运行/ time:2007-5-20 17:41:09
本文主题,1,ASP,NET