在ASP.NET 2.0中建立站点导航层次
站点导航API--站点导航API用于在应用程序的代码中访问站点导航信息,它摘录了导航信息存储的细节。你可以使用API来编程访问应用程序的导航节点。
导航控件--导航控件为页面之间的导航提供了通用的UI,例如树视图、菜单和breadcrumb("面包屑",一种显示当前所在页面的控件)。这些控件利用ASP.NET 2.0中的站点导航服务来检索你给站点定义的结构。SiteMapDataSource控件还允许你把其它UI控件绑定到站点导航数据。
网站经常需要显示导航数据,来指导用户如何使用站点。ASP.NET中的导航特性允许开发者简单地定义导航数据,并根据这些信息来显示UI。
站点导航API是一种用于访问站点导航数据的基于提供程序(provider)的编程内容。该API把导航数据存储在XML文件中,并通过一组SiteMapNode类来暴露这些数据。应用程序和控件开发者可以构建SiteMapNode实例并使用这些信息来显示导航界面。
面向导航的服务器控件包括Menu、TreeView、SiteMapPath和SiteMapDataSource控件。这些控件都是建立在站点导航类的顶端的,它们使用和显示导航数据的时候都是不考虑数据存储的特定细节问题的。Menu和TreeView控件还可以使用XML文件的数据和XMLDataSource控件的数据。
Url映射特性允许开发者为不同URL请求的重映射(re-mapping)定义简单的规则。
使用站点导航控件
Menu、TreeView、SiteMapPath和SiteMapDataSource控件根据导航数据生成导航界面。导航数据可以存储在XML文件中,或者利用站点导航特性的基于提供程序的能力来保存。下面的例子演示了如何组合使用站点导航特性的不同控件。
建立应用程序站点地图
示例的导航结构存放在Web.sitemap文件中,在下面你可以看到站点地图文件。Web.sitemap文件包含一个顶层的<siteMap>元素。在<siteMap>元素内至少嵌套一个<siteMapNode>元素。在一个站点地图内必须有一个顶层的<siteMapNode>。站点导航特性需要一个根<siteMapNode>来确保沿着节点层次的访问最终汇聚到一个已知的节点。你可以在根<siteMapNode>元素下嵌套多个<siteMapNode>元素。此外,嵌套<siteMapNode>元素的深度是没有限制的。
一个<siteMapNode>元素通常包含Url(链接)、Title(标题)和Description(描述)属性。Url属性指明与应用程序中的页面对应的路径。它也可以包含其它应用程序中的页面的路径,或者指向完全不同的网站的多个URL。在下面的例子中,所有的Url属性都使用应用程序相对语法来引用路径。Title属性用于显示导航数据UI的文本内容。例如,SiteMapPath控件把Title属性作为控件的超链接文本显示。如果提供了Description属性,服务器控件就把显示为工具条提示或ALT文本。开发者也可以给<siteMapNode>添加自定义属性,利用SiteMapNode类的默认索引器(indexer)就可以检索这些属性了。你可以查阅.NET框架组件文档找到更多的关于<siteMapNode>元素其它一些属性的信息。
Web.sitemap的内容
<siteMap>
<siteMapNode title="Home" url="~/default.aspx" >
<siteMapNode title="Introduction to ASP.NET" url="~/introduction/default.aspx">
<siteMapNode title="What's New in Whidbey?" url="~/introduction/whatsnew.aspx"/>
<siteMapNode title="Sample Applications (Starter Kits)" url="~/introduction/starterkits.aspx"/>
<siteMapNode title="Introduction to Visual Web Developer" url="~/introduction/vwd.aspx"/>
</siteMapNode>
<siteMapNode title="Building A Web Application" url="~/development/default.aspx">
<siteMapNode title="Building a Simple Application" url="~/development/simple/default.aspx">
<siteMapNode title="Introduction to ASP.NET pages" url="~/development/simple/pages.aspx"/>
……
</siteMapNode>
</siteMapNode>
</siteMap>
使用站点导航控件
在Web页面上提供站点导航的最简单办法就是使用图形化的站点导航控件(SiteMapPath、TreeView和 Menu)。
· SiteMapPath--一个breadcrumb控件,它检索用户的当前页面并显示页面的层次结构。这让用户可以导航回层次中其它的页面。SiteMapPath只能与SiteMapProvider一起使用,需要设置控件的SiteMapProvider属性。
· TreeView--在Web页面上提供垂直的用户界面,它可以展开和收缩选中的节点,也可以提供检查框功能以供用户选择数据项。TreeView控件支持宣告式的或编程设置数据元素和数据源控件。如果你使用SiteMapDataSource控件,那么数据绑定就是自动进行的。
· Menu--提供水平的或垂直的用户界面,当用户把鼠标放在一项上的时候会弹出子菜单。Menu控件支持宣告式的或编程设置数据元素或数据源控件。如果你使用SiteMapDataSource控件,数据绑定就是自动进行的。
请注意,TreeView和Menu控件都可以用于非导航的情形。
下表描述了TreeView和Menu之间的差别,以便于你能根据需要做出适当的选择。
特性 Menu TreeView
扩展 弹出 位置扩展
根据需要下载 No Yes
检查框 No Yes
模板 Yes No
布局 水平 & 垂直 垂直
Style选项 Yes Yes
选择模式 静态的、 动态的层次 层次或父/根/叶,或按数据项
在下面的例子中,你看到的TreeView和Menu控件为不同的区域和操作(例如NodeStyle和HoverNodeStyle)配置了一些样式属性。例子中的TreeView和Menu控件都连接到页面上的同一个SiteMapDataSource控件。SiteMapPath控件通过Web.config文件中设置的默认的SiteMapProvider来访问相同的数据。
<asp:treeview ID="TreeView1" ForeColor="White" DataSourceId="SiteMapDataSource1" NodeIndent="0" NodeStyle-ChildNodesPadding="10" runat="server">
<LevelStyles>
<asp:TreeNodeStyle Font-Bold="true"/>
<asp:TreeNodeStyle />
<asp:TreeNodeStyle Font-Size="x-small"/>
</LevelStyles>
<nodestyle forecolor="White" HorizontalPadding="5"/>
<SelectedNodeStyle backcolor="lightblue" forecolor="blue" />
<HoverNodeStyle Font-UnderLine="true" />
</asp:treeview>
<asp:sitemappath id="SiteMapPath1" runat="server" />
<asp:Menu ID="Menu1" DataSourceId="SiteMapDataSource1" runat="server">
<DynamicSelectedStyle BackColor="lightblue" ForeColor="Blue" />
<DynamicHoverStyle Font-Underline="true" />
<StaticHoverStyle Font-Underline="true" />
</asp:Menu>
<asp:sitemapdatasource id="SiteMapDataSource1" runat="server" />
使用站点导航API
站点导航API是使用可配置的提供程序访问导航数据的编程抽象内容。站点导航提供程序把导航数据的存储细节信息与API的其它部分隔离开来。站点导航API通过SiteMap和SiteMapNode类来暴露导航数据。SiteMap类返回与当前页面对应的SiteMapNode实例。它还可以访问那些为站点导航特性配置的提供程序。SiteMapProvider为执行下面一些事务提供了丰富的API:
· 依据当前的HttpContext或任意URL检索SiteMapNode实例。
· 检索SiteMapNode的父或子节点。
· 访问当前页面的SiteMapNode,以及整个导航层次中的根SiteMapNode。
· 执行授权规则,这样就保证了提供程序只返回用户可以看见的节点。
SiteMapNode实例暴露的基本导航信息和功能包括:
· URL、Title和description属性,以及开发者给SiteMapNode添加的自定义属性。
· 获取某个节点的父和子节点。
· 在某个节点的前后节点之间进行导航。
· 获取SiteMapProvider实例的指针,它返回一个节点。
ASP.NET发布的时候带有XmlSiteMapProvider提供程序。该提供程序使用XML文件(web.sitemap)中的数据,并根据数据返回SiteMapNode实例。XmlSiteMapProvider有下面一些功能:
· 多个站点地图(sitemap)文件可以链接在一起来构建一个"虚拟的"导航数据集合。
· 多个XmlSiteMapProvider实例可以链接到一起来构建一个"虚拟的"导航数据集合。
· 提供程序可以根据站点当前的文件授权和URL授权规则来返回过虑后的节点。
有了SiteMapProvider指针之后,你就可以根据URL来检索特定节点的站点导航数据。它会让你获取站点导航数据中的SiteMapNode实例指针。可以检索任意SiteMapNode实例的能力和从任何SiteMapNode开始进行站点导航的能力组合在一起,使你能够轻易地遍历站点的导航数据。
作为一名开发者,你也可以把导航数据用其它的格式进行存储(例如作为关系数据存储在数据库中)。接着你应该构建一个衍生自SiteMapProvider的自定义提供程序。
使用站点导航类编程
你可以在代码中编程获取导航数据。编程获取站点导航数据的出发点是SiteMap类。在这个类中有大量的静态方法,其中最重要的一个是CurrentNode属性。在网站的任何页面中,你都可以调用SiteMap.CurrentNode来引用与当前的执行页面相匹配的导航数据片断。导航数据是用SiteMapNode实例的形式返回的--当你调用SiteMap.CurrentNode的时候,该属性返回与当前页面对应的SiteMapNode实例。站点导航特性根据存储在XML文件中的导航数据返回正确的节点。
下面的例子演示了一个带有简单的分页功能的用户控件。在显示的页面中,用户控件位于页面的底部中间。最初该链接的内容是"下一个主题"。当你点击这个链接的时候,用户控件调用SiteMapNode对象来检测当前页面的附近是否存在页面。代码检测SiteMap.CurrentNode属性,看它的前面是否有页面(SiteMap.CurrentNode.PreviousSibling)、它的后面是否有页面(SiteMap.CurrentNode.NextSibling)。如果存在页面,用户控件就显示超链接,并把超链接的NavigateUrl属性设置为附近节点的Url属性。
如果你点击页面左部的Treeview链接,可以看到用户控件是如何自动地显示适当的"前一个主题"和"后一个主题"链接的。用户控件还显示了另外一个超链接,你可以点击它返回主页。如果你查看这个超链接如何工作就会发现,该控件利用了主页<siteMapNode>元素中的自定义属性"customAttribute"。该控件演示了如何使用SiteMapNode的默认索引器来检索自定义属性的值。
<script language="VB" runat="server">
Sub Page_Load()
If (Not SiteMap.CurrentNode.NextSibling Is Nothing) Then
NextTopic.NavigateUrl = SiteMap.CurrentNode.NextSibling.Url
Else
NextTopic.Visible = false
Separator.Visible = false
End If
If (Not SiteMap.CurrentNode.PreviousSibling Is Nothing)
PrevTopic.NavigateUrl = SiteMap.CurrentNode.PreviousSibling.Url
Else
PrevTopic.Visible = false
Separator.Visible = false
End If
'使用FindSiteMapNode查找URL中的节点并提取一些信息
Dim rootNode as SiteMapNode = SiteMap.Provider.FindSiteMapNode("~/Home.aspx")
GoHome.NavigateUrl = rootNode.Url
GoHome.ToolTip = rootNode.Description
GoHome.Text = rootNode("customAttribute")
End Sub
</script>
站点导航的安全性
站点导航特性可以根据授权规则过虑提供程序所返回的SiteMapNode实例。XmlSiteMapProvider可以根据当前网站使用的文件和URL授权规则过虑节点。
下面的例子使用了窗体授权规则,预定义的用户凭证存储在web.config中。在global.asax中,根据用户名,用户的角色都被附加到当前的请求上。在web.config中,嵌套在<siteMap>元素之下的站点地图提供程序使用的<add>元素的securityTrimmingEnabled属性被设置为真。同时,web.config文件的末尾定义了一组URL授权规则。当你运行示例并登陆之后,XmlSiteMapProvider会自动地依据用户所属的角色和web.config中定义的授权规则来对SiteMapNode执行授权检测。
请使用下面三个帐户之一运行示例:
· Userid: SectionOne Password: SectionOne
· Userid: SectionTwo Password: SectionTwo
· Userid: AllSections Password: AllSections
在页面的右上角有一个"退出"链接,因此你可以用不同的帐号登陆和退出。请注意,根据你登陆所使用的帐号不同,导航UI显示的Treeview和Menu控件会自动地反映该用户所获得的访问权限。提供程序自动地过虑了返回的节点--实现这种功能不需要额外的代码。用"SectionOne"帐号登陆的时候,只在左边的Treeview控件中显示"SectionOne"链接和外部链接。用"SectionTwo"帐号登陆的时候,只在左边的Treeview控件中显示"SectionTwo"链接和外部链接。用"AllSections"帐号登陆的时候,Treeview控件中显示了所有的链接。web.config中的授权规则配置为给"SectionOne"和"SectionTwo"层次授予了部分访问权力。
这个示例还演示了如何处理应用程序目录范围之外的URL安全性。在web.sitemap文件中,外部链接的节点使用了roles属性。语法roles="*"授予所有用户访问和查看导航控件中的节点的权力。语法roles="Adminstrators,Regular Users"只允许这些角色的用户检索和查看导航控件中的节点。由于在示例中global.asax文件把用户分成了这两种角色,所以你一直可以看到外部链接。
开发者可以选择同时使用文件/URL授权规则和roles属性来控制用户对SiteMapNode实例的访问权。如果两者的设置信息都是正确的,站点导航提供程序就会根据文件/URL授权规则和roles属性中的角色来对当前用户进行认证。如果当前用户通过了任何一种授权检查,就可以访问节点。
如果默认的安全性操作不适用于你的应用程序,开发者还可以从XmlSiteMapProvider衍生类,并用自定义的节点授权实现来重载IsAccessibleToUser方法。
Web.config的内容
<system.web>
<authentication mode="Forms">
<forms name=".ASPXAUTH" loginUrl="Login.aspx" protection="All" timeout="30" path="/" requireSSL="false" slidingExpiration="true" defaultUrl="Home.aspx" cookieless="UseCookies" enableCrossAppRedirects="false">
<credentials passwordFormat="Clear">
<user name="SectionOne" password="SectionOne"/>
<user name="SectionTwo" password="SectionTwo"/>
<user name="AllSections" password="AllSections"/>
</credentials>
</forms>
</authentication>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
<location path="SectionOne.aspx">
<system.web>
<authorization>
<allow users="SectionOne" roles="Administrators" />
<deny users="*"/>
</authorization>
</system.web>
</location>
<location path="SectionOne">
<system.web>
<authorization>
<allow users="SectionOne" roles="Administrators"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
<location path="SectionTwo.aspx">
<system.web>
<authorization>
<allow users="SectionTwo" roles="Administrators"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
<location path="SectionTwo">
<system.web>
<authorization>
<allow users="SectionTwo" roles="Administrators"/>
<deny users="*"/>
</authorization>
</system.web>
本地化站点地图数据
存储在sitemap文件中的导航数据可能需要进行本地化(localize)。<siteMapNode>元素中的URL、Title和Description属性也可以本地化。此外,开发者放置在<siteMapNode>元素中的任何自定义属性也可以本地化。
下面的示例包含了英语和法语的本地化文本。它的web.sitemap文件使用两种类型(隐式的和显式的)的本地化表达式来实现这种功能。Sitemap文件在根siteMap元素中使用了enableLocalization=true就表明它使用了本地化数据。
站点地图文件的隐式表达式让开发者能够轻易地用查找键(lookup key)标记每个<siteMapNode>元素,而查找键是用于从资源文件检索资源的。在示例的web.sitemap中,除了第一个节点之外,所有的节点都有隐式的资源表达式。它的语法类似resourceKey="Autos"。当XmlSiteMapProvider根据web.sitemap文件中的信息检索SiteMapNode的时候,它根据SiteMapNode属性的名称、resourceKey和为提供程序配置的siteMapFile属性的值来检索字符串资源。使用示例中的"Autos"节点的时候,提供程序(provider)会根据当前的文化来查找以"web.sitemap"开头的资源文件。这意味着,对于一个发送法语头信息的浏览器来说,提供程序会查找名称为web.sitemap.fr.resx的资源文件。在这个资源文件中,提供程序会依据resourceKey + "." + [SiteMapNode属性名]来查找资源键。例如,把"Autos"节点的Title属性当作例子,提供程序会在web.sitemap.fr.resx资源文件中查找键为Autos.Title的资源。
显式表达式使开发者对包含本地资源的文件和资源键(resource key)的名称有更强的控制能力。在示例web.sitemap中,第一个<siteMapNode>元素使用了显式资源表达式。显式表达式在每个属性上指定。第一个<siteMapNode>元素的Title属性使用了显式表达式。显式表达式必须以$resource:开头。在这个标识符之后,开发者必须提供资源文件的根名称和资源键。开发者可以选择提供一个默认值。在例子中,表达式$resources: Title, MyTitle , Home表明提供程序应该查看以"Title"开头的资源文件。对于发送法语头信息的浏览器开说,提供程序会查找Title.fr.resx资源文件。接下来提供程序查看键为MyTitle的资源。如果提供程序无法找到这种资源,它会把字符串"Home"作为默认值。
你可以运行示例来查看站点地图本地化的效果。把英语作为默认语言的浏览器会显式英语文本。如果使用IE,你可以通过点击"工具->Internet选项",并在"通用"选项卡点击"语言"按钮,点击"添加"按钮并选择添加"法语"。如果需要,还需要选中法语并点击"向上移动"按钮,使它成为IE的默认请求语言。把默认的语言改成法语之后,刷新示例页面。请注意,Menu、Treeview和SiteMapPath控件中的文本自动地显式为App_GlobalResources目录中存放的法语资源文件中的法语文本。
Web.sitemap的内容
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" enableLocalization="true">
<siteMapNode url="~/Default.aspx" title=" $resources: Title, MyTitle , Home" description="Default page description when no localized value exists." >
<siteMapNode url="~/Category.aspx" resourceKey="Category">
<siteMapNode title="Autos" description="Autos" url="~/Autos.aspx" resourceKey="Autos" />
<siteMapNode title="Games" description="Games" url="~/Games.aspx" resourceKey="Games" />
<siteMapNode title="Health" description="Health" url="~/Health.aspx" resourceKey="Health" />
<siteMapNode title="News" description="News" url="~/News.aspx" resourceKey="News" />
</siteMapNode>
</siteMapNode>
</siteMap>
修改提供程序(Provider)返回的站点导航数据
存储在web.sitemap中、供XmlSiteMapProvider使用的导航数据是静态的--这些数据被载入内存中并作为只读数据存储。但是,很多站点的导航结构是根据查询字符串的值来参数化的。例如,新闻组(newsgroup)站点可能拥有良好定义的页面结构(例如,主页、新闻类别页面和新闻内容页面),但是实际的内容可能会有很大的不同,这依赖于查询字符串中的标识符。尽管把每种可能的查询字符串值都存储在<siteMapNode>元素中也是可能的,但是即使是中等数量的查询字符串值,也要求sitemap文件包含数百个<siteMapNode>元素。
站点导航特性在SiteMapProvider基类中暴露了SiteMapResolve事件。可以使用SiteMap.SiteMapResolve或直接使用提供程序SiteMap.Provider.SiteMapResolve来执行这个事件。这个事件的返回值是一个SiteMapNode实例。你可以在自己的事件处理程序中编写自定义逻辑来建立SiteMapNode实例的层次结构。这个逻辑可以修改每个SiteMapNode的属性,因此URL和Title等属性会反映查询字符串带有的数据信息。
下面的例子在global.asax中注册了一个事件处理程序。这个事件处理程序的代码是App_Code目录中的一个类。这个自定义的类复制与当前页面对应的SiteMapNode实例。XmlSiteMapProvider返回的节点都是只读的,而调用SiteMapNode上的Clone方法返回的是可写入的节点。在实例中,如果给Clone传递了true值,将导致当前的SiteMapNode和它的所有父节点都是可写入的。这个类的代码的其它部分检查当前的页面和当前页面的查询字符串,确定当前页面位于站点层次结构的什么位置。代码修改了URL和Title属性,包含一些额外的信息,这样SiteMapPath控件显示的导航UI就反映了网站用户为到达当前页面的实际点击路径。
运行示例的时候,你开始位于站点的主页。SiteMapPath控件也反映了这一点。点击任何链接都会带你进入分类页面,它显示相关新闻类别中的新闻链接。请注意,如果你把鼠标停留在SiteMapPath控件的最后一个链接上,浏览器状态栏中显示的URL包含了查询字符串信息(它指定了新闻类别)。点击任何一个发布链接都会把你带回到新闻发布页面。如果你把鼠标停留SiteMapPath控件的链接上,可以注意到控件中的最后两个链接带有的URL和Title包含了点击路径的正确查询字符串和描述信息。如果你导航到站点的主页,并点击其它的新闻组和内容链接,SiteMapPath控件会被更新并反映第二次点击的链接。
Public Class PathExpansionHandler
Public Shared Function ExpandPath(ByVal sender As Object, ByVal e As SiteMapResolveEventArgs) As SiteMapNode
'获取当前和之前节点的引用
Dim nodeCopy As SiteMapNode = SiteMap.CurrentNode.Clone(True)
Dim tempNode As SiteMapNode = nodeCopy
'Check if there is a newsgroup type in the query string
Dim typeID As String = Nothing
Dim typeIDUrlEncoded As String = Nothing
If Not String.IsNullOrEmpty(e.Context.Request.QueryString("type")) Then
typeID = e.Context.Server.HtmlEncode(e.Context.Request.QueryString("type"))
typeIDUrlEncoded = e.Context.Server.UrlEncode(e.Context.Request.QueryString("type"))
End If
'首先执行发布页面URL的固定
'如果查询字符串中包含发布ID,我们就知道当前节点式发布页面
If Not String.IsNullOrEmpty(e.Context.Request.QueryString("postingID")) Then
Dim postingID as string = _
e.Context.Server.HtmlEncode(e.Context.Request.QueryString("postingID"))
Dim postingIDUrlEncoded as string = _
e.Context.Server.UrlEncode(e.Context.Request.QueryString("postingID"))
Dim NewUrl As String = tempNode.Url + "?type=" + typeIDUrlEncoded + "&postingID=" + postingIDUrlEncoded
Dim NewTitle As String = tempNode.Title + ": " + postingID
tempNode.Url = NewUrl
tempNode.Title = NewTitle
tempNode = tempNode.ParentNode
End If
'然后,对新闻组页面进行固定
'这时候nodeCopy 变量知贤了新闻组节点
If Not String.IsNullOrEmpty(e.Context.Request.QueryString("type")) Then
Dim NewUrl As String = tempNode.Url + "?type=" + typeIDUrlEncoded
Dim NewTitle As String = tempNode.Title + ": " + typeID
tempNode.Url = NewUrl
tempNode.Title = NewTitle
End If
'最后返回当前节点
Return nodeCopy
End Function
End Class
URL映射
URL映射特性利用web.config中存储的配置信息把收到的请求重映射(remap)到不同的URL。重映射发生在对请求的所有其它处理操作之前。下面的例子演示的是重映射一个页面请求,实际上任意文件类型都可以把请求重映射到不同的URL。
定义重映射URL
URL映射的配置信息存储在web.config中。<urlMappings >元素中嵌套的每个<add>元素为重映射进入站点的(inbound)url定义了一条规则。url属性定义了进入站点的url的exact(原样)属性,URL映射特性会试图用它进行匹配操作。如果exact匹配操作发生了,就会给进入站点的URL重新写入mappedUrl属性值。请注意,这个特性不支持更高级的规则(例如基于通配符和正则表达式的匹配)。
示例web.config为大量的url定义了映射规则。示例使用的web.sitemap文件定义的大量带有URL值的节点都会被重映射。其结果是,URL映射和站点导航的组合使用,使得开发者可以用友好的url来定义导航结构,并使用URL映射把请求重新写到不同的页面来执行实际的处理过程。
当你运行示例的时候,请注意Menu和Treeview控件是如何根据web.sitemap文件中定义的站点结构来显示导航数据的。如果你把鼠标停留在Treeview控件或右上角的SiteMapPath控件的链接上方,状态栏中显示的url是一个友好的url链接。当你点击任何导航链接的时候,实际运行的页面是Default.aspx。但是,Menu、Treeview和SiteMapPath控件中的导航信息仍然反映为友好的URL结构。
在页面的底部你还可以看到Request.Path、Request.QueryString["category"]和Request.RawUrl返回的值。Request.Path和Request.QueryString["category"]返回的值一直反映重映射进入站点的url的结果。但是,Request.RawUrl的值反映了重映射之前的友好的url。当站点导航特性试图把url信息与sitemap文件包含的数据进行匹配的时候,它会使用Request.RawUrl。如果匹配的值没有找到,XmlSiteMapProvider就把Request.Path作为替代者。在例子中,所有的友好url在web.sitemap文件中都有条目,因此使用站点导航的控件一直根据友好的url来显示和引用节点。
<?xml version="1.0" ?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.web>
<urlMappings enabled="true">
<add url="~/Category.aspx" mappedUrl="~/Default.aspx?category=default" />
<add url="~/Autos.aspx" mappedUrl="~/Default.aspx?category=autos" />
<add url="~/Games.aspx" mappedUrl="~/Default.aspx?category=games" />
<add url="~/Health.aspx" mappedUrl="~/Default.aspx?category=health" />
<add url="~/News.aspx" mappedUrl="~/Default.aspx?category=news" />
</urlMappings>
</system.web>
</configuration>
相关文章:

加速数据中心变革,Xilinx推出软件定义、硬件加速型 Alveo SmartNIC
近日,为满足现代数据中心发展需求,赛灵思公司宣布推出一系列全新数据中心产品及解决方案,包括全新 Alveo SmartNIC 系列、smart world (智能世界) AI 视频分析应用、一款能够实现亚微秒级交易的加速算法交易参考设计&a…

跟阿里云技术专家阙寒一起深度了解视频直播CDN技术
网络直播平台现下已经十分火热,很多常见的直播平台都采用了阿里云直播CDN来搭建自身业务。今天,我们请来了阿里云CDN团队技术专家阙寒,来介绍下视频的一些基础知识和视频直播的架构。在进入正题之前,我们先来了解视频直播相关的名…

一个ASP.NET中使用的MessageBox类
/// <summary>/// 自定义信息对话框/// </summary>public class MessageBox{/// <summary>/// 定义一个web页面,用来显示用户自定错误提示信息/// </summary>System.Web.UI.Page p;/// <summary>/// 实例时,参数为:this 如…

Ubuntu 13.10 安装Terminalx 后更改默认终端设置
1、安装 terminalx, sudo apt-get install terminator 2、Ctrl Alt t 试一下打开什么终端,我的默认启动的是Terminator;如果想换换默认的终端,还需以下一步 3、接下来,安装dconf-tools,这个是设置默认终端的必须 打开…

360数科张家兴:如何突破三大瓶颈,破解金融科技发展难题?
3月6日,上海香港联会、普陀香港联会联合普陀新区联会,IFTA亚洲金融科技师学会共同举办了“沪港合作共创未来”——沪港两地金融科技线上论坛。本次活动通过沪港两地直播连线,探讨两地金融科技领域的发展机遇。麻省理工学院香港创坊执行董事冼…

通过改进算法来优化程序性能的真实案例(Ransac)
对于运行不了几次,一次运行不了多久的方法,我们不需要考虑性能优化,对于那些需要经常运行几百次几千次的方法,我们头脑里还是要有性能这根弦。C#太优雅方便了,以至于很多人写程序时根本就把性能抛到脑后了,…

ASP.NET中使用MD5和SHA1算法加密
你的主页或者你管理的网站有各种密码需要保护,把密码直接放在数据库或者文件中存在不少安全隐患,所以密码加密后存储是最常见的做法。在ASP.NET中实现加密非常容易。.NET SDK中提供了CookieAuthentication类,其中的HashPasswordForStoringInC…

不追逐标准化产品,360数科的一站式风控体系有何不同?
新冠肺炎疫情无疑加速了金融行业数字化转型,竞争者不断涌入,逐渐形成由BATJ、传统银行旗下金融科技子公司、以及专注于金融机构的数字化服务公司构成的竞争格局。然而,风控始终是金融行业的核心。作为定位于中国零售金融领域科技服务商的360数…

基于Bootstrap里面的Button dropdown打造自定义select
最近工作非常的忙,在对一个系统进行改版。项目后台是MVC1.0开发的,但是前端部分已经改过几个版本,而已之前的设计师很强大,又做设计又做前端开发。而已很时尚和前沿,使用了一直都很热门的Bootstrap工具包,有…

HybridDB · 源码分析 · MemoryContext 内存管理和内存异常分析
背景 最近排查和解决了几处 HybridDB for PostgreSQL 内存泄漏的BUG。觉得有一定通用性。 这期分享给大家一些实现细节和小技巧。 阿里云上的 HybridDB for PostgreSQL 是基于 PostgreSQL 开发,定位于 OLAP 场景的 MPP 架构数据库集群。它不少的内部机制沿用了 Post…

联合南京大学,爱奇艺智能论文入选顶会CVPR 2021
日前,全球计算机视觉顶级会议CVPR (IEEE Conference on Computer Vision and Pattern Recognition)公布了2021年论文接收结果。作为计算机视觉领域世界三大顶会(CVPR、ICCV、ECCV)之一,CVPR的论文投稿量近五年来持续大涨。据CVPR官网显示,今…

Forefront_TMG_2010-TMG发布Web服务器
1.环境拓扑图:2.准备DMZ区域的Web服务器:安装Web服务器:在DMZ区域的Web服务器进行测试:3.TMG发布Web服务器:打开TMG管理控制台,新建“网站发布规则”:新建名称:选择“允许”…

ASP.NET实现身份模拟
使用模拟时,ASP.NET 应用程序可以选择以这些应用程序当前正为之操作的客户的身份执行。通常这样做的原因是为了避免在 ASP.NET 应用程序代码中处理身份验证和授权问题。而您依赖于 Microsoft Internet 信息服务 (IIS) 来验证用户,然后将已通过验证的标记…

Mac homebrew类似apt-get命令安装包
INSTALL brew ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 其它: 其他brew命令 brew list 列出已安装的软件 brew update 更新brew brew home 用浏览器打开brew的官方网站 brew inf…

asp.net中长内容自动分页的实现
在一篇文章过长时,可以自动的写个小程序对其进行分页.具体代码:public class t3 : System.Web.UI.Page { private string str;//字符 private int strl;//字符总长度 private int pagesize;//每页显示的字符数 …

黑马程序员之List--队列、栈...
--------------------- ASP.NetUnity开发、.Net培训、期待与您交流! ---------------------- 1.队列:先进先出 运行结果: zhangsan lisi wangwu 2.栈:先进后出 结果: lisi wangwu zhangsan 3. 去除重复元素思路&#x…

龙芯架构应用迁移技术分享——搜狗输入法应用迁移
技术引领创新,用“芯”构建生态,第一期龙芯生态论坛将于2021年3月12日(周五)盛大开讲!龙芯生态论坛作为龙芯生态建设的重要技术交流窗口,将汇聚龙芯资深技术专家及行业生态伙伴精英,持续开展行业…

Health Check in eShop -- 解析微软微服务架构Demo(五)
引言 What is the Health Check Health Check(健康状态检查)不仅是对自己应用程序内部检测各个项目之间的健康状态(各项目的运行情况、项目之间的连接情况等),还包括了应用程序对外部或者第三方依赖库的状态检测。 Why…
网易伏羲论文入选 CVPR:AI 感知表情能力或实现巨大突破!
出品 | AI科技大本营(ID:rgznai100)2月28日,人工智能顶级会议CVPR 2021(国际计算机视觉与模式识别会议,Conference onComputer Vision and Pattern Recognition)公布论文录取结果,网易伏羲共有3…

asp.net/c#字符格式化大总结
一、用{0:?}格式化可通过 String.Format 方法或通过 Console.Write 方法格式化数值结果,其中后一种方法调用 String.Format。使用格式字符串指定格式。下表包含受支持的标准格式字符串。格式字符串采用的形式为 Axx,其中 A 为“格式说明符”,…

小鱼提问1 类中嵌套public修饰的枚举,外部访问的时候却只能Class.Enum这样访问,这是为何?...
/// <summary>/// 常量等定义/// </summary>public class General{/// <summary>/// 文件类型/// </summary>public enum FileType{}}小鱼提问:都是public修饰,为何外部只能General.FileType这样访问?既然外部都不能…

radio根据name 获取选中值及判断是否被选中
$(input:radio[name"fjscfs"]:checked).val();根据id判断是否被选中if($("#A26").is(":checked")){}根据class判断是否被选中if($(".A26").is(":checked")){}转载于:https://blog.51cto.com/ty2538402559/1949828

ASP.NET中用healthMonitor属性用
在ASP.NET 2.0中,可以使用healthMonitoring属性监测事件。healthMonitoring属性是一个基于方法的provider,在这里可以构造自己的provider。利用healthMonitoring属性,我们可以诸如记录错语、成功的事件等,对不同的数据源ÿ…

用 Python 动态可视化,看看比特币这几年
作者 | 刘早起来源 | 早起Python头图 | 下载于视觉中国最近几年,一直站在风口浪尖的比特币被追捧为最佳的投资产品,拥护者们认为这种加密货币是一种类似于黄金的储值工具,可以对冲通胀和美元疲软。其他人则认为,比特币的暴涨只是一…

违规用户处理办法
2019独角兽企业重金招聘Python工程师标准>>> 1.简单设置用户信赖状态 给用户设置信任字段,0不可信任,1默认许可(默认值),2可信赖用户 当用户违规后,对其进行惩罚并设置其为 不可信赖状态&#…

linux同步软件
linux同步软件:scp,rsync,inotify,sersync一、scpscp就是secure copy,是用来进行远程文件拷贝的。数据传输使用 ssh,并且和ssh 使用相同的认证方式,提供相同的安全保证 。 与rcp 不同的是,scp 在需要进行验证时会要求你…

C语言内联函数
内联函数也称内嵌函数,它主要解决程序的运行效率。 #####################问题######################################### 函数调用需要建立栈内存环境,进行参数传递,并产生程序执行转移,这些转移都需要时间开销。 有些函数在程序…

Maximum Subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest sum. For example, given the array [−2,1,−3,4,−1,2,1,−5,4],the contiguous subarray [4,−1,2,1] has the largest sum 6. Code: class Solution { public:int …

从Python到AI,这条路好走吗?
大家都在学Python的时候,怎么才能让自己更有竞争力?Python 的应用方向有很多,基本每个方向都是大热门,但至今为止,人工智能行业仍处于人才稀缺的情况。正因这样,近几年来,AI 成为了广大 Python …

微信小程序server-1-搭建HTTPS server
一.使用 Node 和 Express 搭建一个 HTTP 服务器 1.在app.js修改小程序通信域名 App({config: {host: // 这个地方填写你的域名},onLaunch () {console.log(App.onLaunch());} }); 2.安装 NodeJS 和 NPM yum install nodejs npm -y node -v 3.编写HTTP服务源码 touch package.j…