Question

Je voudrais faire correspondre & "approximativement &"; correspond à Web.SiteMap

Le fournisseur de plan de site statique de Web.Sitemap fonctionne bien, à une exception près. C'EST STATIQUE!

Donc, si je devais avoir un noeud sitemap pour chacun des 10 000 articles de ma page, comme ceci:

  • site.com/articles/1/article-title
  • site.com/articles/2/another-article-title
  • site.com/articles/3/another-article-again
  • ...
  • site.com/articles/9999/the-last-article

Existe-t-il une sorte de mappage générique que je peux faire avec le plan de site pour faire correspondre tout ce qui se trouve sous Articles?

Ou peut-être dans ma page Webforms, existe-t-il un moyen de définir manuellement le nœud actuel?

J'ai trouvé un " bit " de l'aide sur cette page lorsque vous le faites avec ASP.Net MVC Framework, mais cherche toujours une bonne solution pour les formulaires Web.

Je pense que ce que je vais devoir faire est de créer un fournisseur SiteMap personnalisé

Était-ce utile?

La solution

Ceci est une réponse au commentaire ci-dessus. Je ne peux pas publier le code complet, mais voici comment mon fournisseur fonctionne.

Supposons que vous ayez une page article.aspx et que le paramètre de chaîne de requête " id " pour récupérer et afficher un titre et un corps d'article. Ensuite, cela se trouve dans Web.sitemap:

<siteMapNode url="/article.aspx" title="(this will be replaced)" param="id" />

Ensuite, vous créez cette classe:

public class DynamicSiteMapPath : SiteMapPath
{
  protected override void InitializeItem(SiteMapNodeItem item)
  {
    if (item.ItemType != SiteMapNodeItemType.PathSeparator)
    {
      string url = item.SiteMapNode.Url;
      string param = item.SiteMapNode["param"];

      // get parameter value
      int id = System.Web.HttpContext.Current.Request.QueryString[param];

      // retrieve article from database using id
      <write your own code>

      // override node link
      HyperLink link = new HyperLink();
      link.NavigateUrl = url + "?" + param + "=" + id.ToString();
      link.Text = <the article title from the database>;
      link.ToolTip = <the article title from the database>;
      item.Controls.Add(link);
    }
    else
    {
      // if current node is a separator, initialize as usual
      base.InitializeItem(item);
    }
  }
}

Enfin, vous utilisez ce fournisseur dans votre code, tout comme vous utiliseriez le fournisseur statique.

<mycontrols:DynamicSiteMapPath ID="dsmpMain" runat="server" />

Mon cours est plus compliqué que cela, mais ce sont les bases. Au lieu d'utiliser un paramètre de chaîne de requête, vous pouvez simplement analyser l'URL conviviale que vous utilisez et l'utiliser pour récupérer le contenu correct. Pour minimiser les recherches de base de données supplémentaires à chaque requête, vous pouvez ajouter un mécanisme de mise en cache au fournisseur (le titre de l'article ne change généralement pas souvent).

J'espère que cela vous aidera.

Autres conseils

Je pense que ce n’est pas tout à fait une réponse à votre question, mais peut-être que cela vous donne une idée. Une fois, j'ai écrit une classe DynamicSiteMapPath héritant de SiteMapPath. J'utilise un attribut personnalisé dans chaque balise <siteMapNode> dans Web.sitemap, comme suit:

<siteMapNode url="dynamicpage.aspx" title="blah" params="id" />

La classe DynamicSiteMapPath obtient ensuite le & "id &"; La valeur du paramètre, récupère le contenu de la base de données et remplace le noeud d'élément de sitemap actuellement rendu par le titre et le lien appropriés. Cela va demander un peu de travail, mais une fois terminé, c’est une manière très soignée de fournir un support dynamique pour les pages.

Je me suis heurté à ce problème et, franchement, je n’ai trouvé aucune solution qui me rende heureux ... alors j’emprunte des idées ici et là. Ma solution est composée de plusieurs parties: a) demandez à SiteMapProvider de trouver la page qui traite la demande et utilisez son noeud, et b) utilisez les techniques standard pour mettre à jour le noeud sitemap à partir de là.

A) Le problème que je rencontrais sans cesse est que si je n’avais pas le chemin virtuel correct, SiteMap.CurrentNode serait null et déclencherait la fonction SiteMapResolve. Pour résoudre ce problème, j'ai sous-classé XmlSiteMapProvider et remplacé CurrentNode:

 namespace WebFormTools
{
    class RouteBaseSitemapProvider : XmlSiteMapProvider
    {
        public override SiteMapNode CurrentNode
        {
            get
            {
                var node = base.CurrentNode;


                if (node == null) 
                {
                    // we don't have a node, see if this is from a route
                    var page = HttpContext.Current.CurrentHandler as System.Web.UI.Page;

                    if (page != null && page.RouteData != null)
                    {
                        // try and get the Virtual path associated with this route
                        var handler = page.RouteData.RouteHandler as PageRouteHandler;

                        if (handler != null) {
                            // try and find that path instead.
                            node = FindSiteMapNode(handler.VirtualPath);
                        }
                    }

                }

                return node;
            }
        }
    }
}

En gros, si l'implémentation par défaut ne trouve rien, recherchez la route (le cas échéant) et essayez de trouver le nœud à l'aide du chemin virtuel du gestionnaire.

Pour référence, voici une partie de mes fichiers Web.Config, Global.asax et SiteMap:

Ajout du fournisseur

    <siteMap defaultProvider="RouteBaseSitemapProvider">
  <providers>
    <add name="RouteBaseSitemapProvider" type="WebFormTools.RouteBaseSitemapProvider" siteMapFile="Web.sitemap" />
  </providers>
</siteMap>

L'itinéraire:

            routes.MapPageRoute("EvalRoutes",
            "Evals/{type}/New.aspx",
            "~/Evals/New.aspx");

Et le plan du site:

        <siteMapNode url="~/Evals/New.aspx" title="New Eval - {type}"  description="" />

B) I sous-classe System.Web.UI.Page, nommée BaseClass, qui ajoute une méthode pour enregistrer les gestionnaires pour l'événement SiteMapResolve:

public System.Web.SiteMapNode Process(System.Web.SiteMapNode currentNode)
    {
        if (currentNode == null) return currentNode;

        var page = HttpContext.Current.CurrentHandler as System.Web.UI.Page;

        if (page != null && page.RouteData != null)
        {

            Dictionary<Regex, string> replacements = new Dictionary<Regex, string>();

            // build a list of RegEx to aid in converstion, using RegEx so I can ignore class.  Technically I could also
            foreach (var key in page.RouteData.Values.Keys)
            {
                replacements.Add(new Regex(string.Format("\\{{{0}\\}}", key), RegexOptions.IgnoreCase), page.RouteData.Values[key].ToString());              
            }


            // navigate up the nodes
            var activeNode = currentNode;
            while (activeNode != null)
            {
                // to the replacements
                foreach(var replacement in replacements)
                {
                    activeNode.Title =  replacement.Key.Replace(activeNode.Title, replacement.Value);
                }

                activeNode = activeNode.ParentNode;
            }

        }

        return currentNode;
    }

J'ai toujours besoin que les URL correspondent correctement (l'URL de la page recevant la route serait utilisée), qui est sans information de routage. J'utiliserai probablement un attribut personnalisé dans le sitemap pour indiquer au nœud comment rendre l'URL.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top