[visual basic]
<script language="vb" runat="server"> sub page_load(sender as object, e as eventargs) { if user.identity.isauthenticated then welcome.text = "欢迎" + user.identity.name else 尚未登录,添加一个指向登录页的链接 welcome.text = "请登录!" welcome.navigateurl = "signin.aspx" end if end sub</script><asp:hyperlink id="welcome" runat="server" maintainstate="false"></asp:hyperlink>
[c#]
<script language="c#" runat="server"> void page_load(object sender, eventargs e) { if (user.identity.isauthenticated) { welcome.text = "欢迎" + user.identity.name; } else { // 尚未登录,添加一个指向登录页的链接 welcome.text = "请登录!"; welcome.navigateurl = "signin.aspx"; } }</script><asp:hyperlink id="welcome" runat="server" maintainstate="false"></asp:hyperlink>
context.items 简介
希望以上示例可以说明,使用手头仅有的上下文信息编写 web 应用程序是多么容易。那么,如果可以用同样的方法访问您应用程序独有的一些上下文,不是很好吗?
这就是 context.items 集合的用途。它使用在参与处理请求的各部分代码中都可用的方法,保存应用程序的请求特有值。例如,同样一条信息可以用在 global.asax、aspx 页、页内的用户控件中,也可以由页调用的业务逻辑使用。
请考虑 ibuyspy portal(英文)应用程序示例。它使用一个简单的主页 desktopdefault.aspx 来显示门户内容。显示的内容取决于所选择的选项卡,以及用户(如果已经过身份验证)角色。

图 2:ibuyspy 主页
查询字符串包含正被请求的选项卡的 tabindedx 和 tabid 参数。在处理请求的整个过程中,一直使用此信息筛选要显示给用户的数据。http://www.ibuyspyportal.com/desktopdefault.aspx?tabindex=1&tabid=2(英文)
要使用查询字符串值,需要首先确保它是一个有效值,如果不是,则要进行一些错误处理。它并不是一大串代码,但是您真的要在每个使用该值的页和组件中复制它吗?当然不!在 portal 示例中,甚至更多的地方都涉及到它,因为一旦我们知道了 tabid,就可以预先加载其他信息。
portal 使用查询字符串值作为参数,以构造一个新的 portalsettings 对象,并将它添加到 global.asax 的 beginrequest 事件的 context.items 中。由于在每个请求开始处都执行了开始请求,这使得与该选项卡有关的值在应用程序的所有页和组件中都可用。请求完成后,对象将被自动丢弃 – 非常整齐!
[visual basic global.asax]
sub application_beginrequest(sender as [object], e as eventargs) dim tabindex as integer = 0 dim tabid as integer = 0 从查询字符串获取 tabindex if not (request.params("tabindex") is nothing) then tabindex = int32.parse(request.params("tabindex")) end if 从查询字符串获取 tabid if not (request.params("tabid") is nothing) then tabid = int32.parse(request.params("tabid")) end if context.items.add("portalsettings", _new portalsettings(tabindex, tabid)) end sub
[c# global.asax]
void application_beginrequest(object sender, eventargs e) { int tabindex = 0; int tabid = 0; // 从查询字符串获取 tabindex if (request.params["tabindex"] != null) { tabindex = int32.parse(request.params["tabindex"]); } // 从查询字符串获取 tabid if (request.params["tabid"] != null) { tabid = int32.parse(request.params["tabid"]); } context.items.add("portalsettings", new portalsettings(tabindex, tabid));}
desktopportalbanner.ascx 用户控件从 context 请求 portalsetting 的对象,以访问 portal 的名称和安全设置。事实上,此模块是操作中的 context 的一个典型综合示例。为阐明这一点,我已将代码进行了一些简化,并用粗体标记了 http 或应用程序特定的 context 被访问过的所有地方。
[c# desktopportalbanner.ascx]
<%@ import namespace="aspnetportal" %><%@ import namespace="system.data.sqlclient" %><script language="c#" runat="server"> public int tabindex; public bool showtabs = true; protected string logofflink = ""; void page_load(object sender, eventargs e) { // 从当前上下文获取 portalsettings portalsettings portalsettings = (portalsettings) context.items["portalsettings"]; // 动态填充门户站点名称 sitename.text = portalsettings.portalname; // 如果用户已登录,自定义欢迎信息 if (request.isauthenticated == true) { welcomemessage.text = "欢迎" + context.user.identity.name + "!<" + "span class=accent" + ">|<" + "/span" + ">"; // 如果身份验证模式为 cookie,则提供一个注销链接 if (context.user.identity.authenticationtype == "forms") { logofflink = "<" + "span class=\"accent\">|</span>\n" + "<a href=" + request.applicationpath + "/admin/logoff.aspx class=sitelink> 注销" + "</a>"; } } // 动态显示门户选项卡条 if (showtabs == true) { tabindex = portalsettings.activetab.tabindex; // 生成要向用户显示的选项卡列表 arraylist authorizedtabs = new arraylist(); int addedtabs = 0; for (int i=0; i < portalsettings.desktoptabs.count; i++) { tabstripdetails tab = (tabstripdetails)portalsettings.desktoptabs[i]; if (portalsecurity.isinroles(tab.authorizedroles)) { authorizedtabs.add(tab); } if (addedtabs == tabindex) { tabs.selectedindex = addedtabs; } addedtabs++; } // 用已授权的选项卡填充页顶部的选项卡// 列表 tabs.datasource = authorizedtabs; tabs.databind(); } }</script><table width="100%" cellspacing="0" class="headbg" border="0"> <tr valign="top"> <td colspan="3" align="right"> <asp:label id="welcomemessage" runat="server" /> <a href="<%= request.applicationpath %>">portal 主页</a><span class="accent"> |</span> <a href="<%= request.applicationpath %>/docs/docs.htm"> portal 文档</a> <%= logofflink %> </td> </tr> <tr> <td width="10" rowspan="2"> </td> <td height="40"> <asp:label id="sitename" runat="server" /> </td> <td align="center" rowspan="2"> </td> </tr> <tr> <td> <asp:datalist id="tabs" runat="server"> <itemtemplate> <a href=<%= request.applicationpath %>/desktopdefault.aspx?tabindex=<%# container.itemindex %>&tabid=<%# ((tabstripdetails) container.dataitem).tabid %>><%# ((tabstripdetails) container.dataitem).tabname %></a> </itemtemplate> <selecteditemtemplate> <span class="selectedtab"><%# ((tabstripdetails) container.dataitem).tabname %></span> </selecteditemtemplate> </asp:datalist> </td> </tr></table>
您可以使用 visual basic 和 c# 在 http://www.ibuyspy.com(英文)联机浏览并运行 ibuyspy portal 的完整源文件,或者下载后再运行。
小结
context 是 asp.net 中的又一个“精益求精”的功能。它扩展了 asp 的已经很不错的上下文支持,以便将两个挂钩添加到 asp.net 的新运行时功能中。同时添加了 context.items,作为短期值的新状态机制。但对于开发人员,此功能的最大好处是使代码更紧凑,且易于维护,而且此上下文我们都能看懂。
