站点地图和 URL 路由

发布于 2024-08-20 07:39:08 字数 1740 浏览 10 评论 0原文

我有一个与此处描述的问题类似的问题:
使用 WebForms 进行 ASP.NET URL 路由 - 使用 SiteMap

我的 ASP.Net WebForms Web 应用程序有一个站点地图,与此类似:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
  <siteMapNode title="Root">
    <siteMapNode url="Home" title="Home" />
      <siteMapNode url="Home?" title="Home" />
      <siteMapNode url="Faq" title="FAQ" />
    </siteMapNode>
    <siteMapNode url="Reports" title="Your reports" />
      <siteMapNode url="Reports?" title="Your reports" />
      <siteMapNode url="ExtraReports" title="Extra reports" />
    </siteMapNode>
    <siteMapNode url="Presentations" title="Your presentations" />
      <siteMapNode url="Presentations?" title="Your presentations" />
      <siteMapNode url="ExtraPresentations" title="Extra presentations" />
    </siteMapNode>
 </siteMapNode>

我想要以下格式的网址:
://host/projects/{公司}/{项目编号}/Home
://host/projects/microsoft/10/Home
://host/projects/microsoft/11/Reports
://host/projects/apple/10/ExtraReports

Url 路由将 /projects/{company}/{projectno}/{pagename} 路由到 /Pages/{pagename}.aspx。

我的导航由顶部的 TabStrip 组成,其中应包含主页、报告和演示文稿,以及左侧的菜单及其子项目(例如,选择主页后,应为:主页、常见问题解答 >)。

我的问题:

  1. 处理重复的 SiteMapNode url 的正确方法是什么?

  2. 如何防止 TabStrip 生成如下 URL:://host/Home 和 ://host/ExtraReports?
    我需要保持当前公司和项目没有选择,并且站点地图忽略相对网址

  3. TabStrip 和 Menu 控件需要识别所选项目以显示活动选择。解决所有这些问题的正确解决方案是什么?

I have a question similar to the one described here:
ASP.NET URL Routing with WebForms - Using the SiteMap

My ASP.Net WebForms webapplication has a Sitemap, similar to this:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
  <siteMapNode title="Root">
    <siteMapNode url="Home" title="Home" />
      <siteMapNode url="Home?" title="Home" />
      <siteMapNode url="Faq" title="FAQ" />
    </siteMapNode>
    <siteMapNode url="Reports" title="Your reports" />
      <siteMapNode url="Reports?" title="Your reports" />
      <siteMapNode url="ExtraReports" title="Extra reports" />
    </siteMapNode>
    <siteMapNode url="Presentations" title="Your presentations" />
      <siteMapNode url="Presentations?" title="Your presentations" />
      <siteMapNode url="ExtraPresentations" title="Extra presentations" />
    </siteMapNode>
 </siteMapNode>

I'd like to have the url in the following format:
://host/projects/{company}/{projectno}/Home
://host/projects/microsoft/10/Home
://host/projects/microsoft/11/Reports
://host/projects/apple/10/ExtraReports

The Url routing routes /projects/{company}/{projectno}/{pagename} to /Pages/{pagename}.aspx.

My navigation consists of a TabStrip on top which should contain Home, Reports and Presentations and a Menu on the left with their subitems (e.g. with Home selected it should be: Home, Faq).

My questions:

  1. What is the proper way to handle the duplicate SiteMapNode urls?

  2. How do I prevent the TabStrip from generating urls like: ://host/Home and ://host/ExtraReports?
    I need to maintain the current company and projectno selection, and the sitemap ignores relative urls

  3. The TabStrip and Menu controls need to recognize the selected items to show the active selection. What is the proper solution to all of this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦醒时光 2024-08-27 07:39:08

在花了几个小时之后,我想我已经找到了一个很好的(足够的:))解决方案。

站点地图文件
注意没有 url 的节点将指向父节点

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
    <siteMapNode>
        <siteMapNode title="Home" url="Home">
            <siteMapNode title="Home" />
            <siteMapNode title="xxx" url="Cycle"/>
            <siteMapNode title="yyy" url="Survey" />
            <siteMapNode title="zzzteam" url="Team" />
        </siteMapNode>
        ...

生成 URL 的实用程序类
CurrentContext 是对 RequestContext 的静态引用

public static string GetPageUrl(SiteMapNode node) {
   RouteValueDictionary values = new RouteValueDictionary(CurrentContext.RouteData.DataTokens);
   values["page"] = node.Url.Trim('/');

   return CurrentContext.RouteData.Route.GetVirtualPath(CurrentContext, values).VirtualPath;
}

MasterPage 中的数据绑定事件
导航是 Telerik Tabstrip,子导航是 ASP.Net 菜单

private void navigation_TabDataBound(object sender, Telerik.Web.UI.RadTabStripEventArgs e) {
   if (!String.IsNullOrEmpty(e.Tab.NavigateUrl)) {              
          SiteMapNode node = (SiteMapNode) e.Tab.DataItem;

   // Is this tab a parent of the current navigation node? Then select it
   if (SiteMap.CurrentNode.IsDescendantOf(node)) e.Tab.Selected = true;
          e.Tab.NavigateUrl = XRouteHandler.GetPageUrl(node);
   }
}

private void subNavigation_MenuItemDataBound(object sender, MenuEventArgs e) {
    SiteMapNode itemNode = (SiteMapNode) e.Item.DataItem;
    SiteMapNode currentNode = SiteMap.CurrentNode;

    // SiteMapNodes without url will point to the parent node
    if (String.IsNullOrEmpty(itemNode.Url)) {
        itemNode = itemNode.ParentNode;
        e.Item.Selectable = true;
    }

    // Is this menu item the node itself or one of it's parents? Then select it
    if (currentNode == itemNode || currentNode.IsDescendantOf(itemNode))
        e.Item.Selected = true;
        e.Item.NavigateUrl = XRouteHandler.GetPageUrl(itemNode);
    }
}

XmlSiteMapProvider 实现
这个解决方案目前已经足够好了,稍后会研究它以美化它:)

public override SiteMapNode FindSiteMapNode(HttpContext context) {
        string pageName = context.Request.Url.Segments.Last().Trim('/');
        foreach (SiteMapNode node in SiteMap.RootNode.GetAllNodes())
                if (node.Url.EndsWith(pageName, StringComparison.InvariantCultureIgnoreCase)) return node;
        return SiteMap.RootNode;
}

After spending a few hours on this, I think I've come to a good (enough :)) solution.

SiteMap file
Notice the nodes without url will point to the parent

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
    <siteMapNode>
        <siteMapNode title="Home" url="Home">
            <siteMapNode title="Home" />
            <siteMapNode title="xxx" url="Cycle"/>
            <siteMapNode title="yyy" url="Survey" />
            <siteMapNode title="zzzteam" url="Team" />
        </siteMapNode>
        ...

Utility class to generate the Url
CurrentContext is a static reference to the RequestContext

public static string GetPageUrl(SiteMapNode node) {
   RouteValueDictionary values = new RouteValueDictionary(CurrentContext.RouteData.DataTokens);
   values["page"] = node.Url.Trim('/');

   return CurrentContext.RouteData.Route.GetVirtualPath(CurrentContext, values).VirtualPath;
}

Databound events in the MasterPage
Navigation is a Telerik Tabstrip, subnavigation is the ASP.Net Menu

private void navigation_TabDataBound(object sender, Telerik.Web.UI.RadTabStripEventArgs e) {
   if (!String.IsNullOrEmpty(e.Tab.NavigateUrl)) {              
          SiteMapNode node = (SiteMapNode) e.Tab.DataItem;

   // Is this tab a parent of the current navigation node? Then select it
   if (SiteMap.CurrentNode.IsDescendantOf(node)) e.Tab.Selected = true;
          e.Tab.NavigateUrl = XRouteHandler.GetPageUrl(node);
   }
}

private void subNavigation_MenuItemDataBound(object sender, MenuEventArgs e) {
    SiteMapNode itemNode = (SiteMapNode) e.Item.DataItem;
    SiteMapNode currentNode = SiteMap.CurrentNode;

    // SiteMapNodes without url will point to the parent node
    if (String.IsNullOrEmpty(itemNode.Url)) {
        itemNode = itemNode.ParentNode;
        e.Item.Selectable = true;
    }

    // Is this menu item the node itself or one of it's parents? Then select it
    if (currentNode == itemNode || currentNode.IsDescendantOf(itemNode))
        e.Item.Selected = true;
        e.Item.NavigateUrl = XRouteHandler.GetPageUrl(itemNode);
    }
}

XmlSiteMapProvider implementation
This solution is good enough for now, will look into it later to prettify it :)

public override SiteMapNode FindSiteMapNode(HttpContext context) {
        string pageName = context.Request.Url.Segments.Last().Trim('/');
        foreach (SiteMapNode node in SiteMap.RootNode.GetAllNodes())
                if (node.Url.EndsWith(pageName, StringComparison.InvariantCultureIgnoreCase)) return node;
        return SiteMap.RootNode;
}
黑白记忆 2024-08-27 07:39:08

Zyphax,

您很可能必须重写 TabStrip 和 Menu 控件以考虑您的路线。这也意味着您可以删除重复的 SiteMapNode。

相反,您需要编写一些代码来遍历 SiteMap 树以获取最远的祖先(主页的子级)。这是一种可能有帮助的扩展方法。

public SiteMapNode FurthestAncestor(this SiteMapNode node)
{
    while (node.Key !=  this.RootNode.Key && node.ParentNode.Key != this.RootNode.Key)
    {
        node = node.ParentNode;
    }

    return node;
}

另外,使用相对 URL 将有助于 ../Presentations 而不是 /projects/apple/10/Presentations

Zyphax,

It's most likely that you are going to have to re-write the TabStrip and Menu controls to take account of your routes. This would also mean that you could remove the duplicate SiteMapNodes.

Instead you would need to write some code to traverse the SiteMap tree to get the furthest ancestor which is a child of the Home page. This is an extension method which might help.

public SiteMapNode FurthestAncestor(this SiteMapNode node)
{
    while (node.Key !=  this.RootNode.Key && node.ParentNode.Key != this.RootNode.Key)
    {
        node = node.ParentNode;
    }

    return node;
}

Also using relative URLs will help ../Presentations rather than /projects/apple/10/Presentations

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文