Карта сайта и маршрутизация URL

У меня есть вопрос, аналогичный описанному здесь:
Маршрутизация URL-адресов ASP.NET с помощью веб-форм - использование карты сайта

В моем веб-приложении ASP.Net WebForms есть карта сайта, подобная этому:

<?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

Маршрутизация URL-адресов routes / projects / {company} / {projectno} / {pagename} to /Pages/{pagename}.aspx.

Моя навигация состоит из TabStrip вверху, который должен содержать Home, Reports и Presentations, и меню слева с их подпунктами (например, при выбранном Home это должно быть: Home, Faq ).

Мои вопросы:

  1. Как правильно обрабатывать повторяющиеся URL-адреса SiteMapNode?

  2. Как запретить TabStrip генерировать URL-адреса, например:: // host / Home и: // host / ExtraReports?
    Мне нужно сохранить текущую выбранную компанию и projectno, а карта сайта игнорирует относительные URL-адреса

  3. Элементы управления TabStrip и Menu должны распознавать выбранные элементы, чтобы отображать активный выбор. Какое правильное решение для всего этого?


person Zyphrax    schedule 29.01.2010    source источник


Ответы (2)


Потратив на это несколько часов, я думаю, что пришел к хорошему (достаточно :)) решению.

Файл SiteMap
Обратите внимание, что узлы без 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, субнавигация - это меню 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;
}
person Zyphrax    schedule 02.02.2010

Зифакс,

Скорее всего, вам придется переписать элементы управления TabStrip и Menu, чтобы учесть ваши маршруты. Это также будет означать, что вы можете удалить повторяющиеся SiteMapNodes.

Вместо этого вам нужно будет написать код для обхода дерева 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

person Phil Peace    schedule 01.02.2010
comment
Я работал над этим сегодня в офисе. Я думаю, что нашел хорошее решение, которое действительно связано с элементами управления TabStrip и Menu. Выложу завтра. Спасибо. - person Zyphrax; 02.02.2010