استخدام Web.SiteMap مع عناوين URL الديناميكية (توجيه عنوان URL)

StackOverflow https://stackoverflow.com/questions/291908

سؤال

أرغب في مطابقة المطابقات "التقريبية" في Web.SiteMap

يعمل موفر خريطة الموقع الثابتة Web.Sitemap بشكل جيد، باستثناء شيء واحد.انها ثابتة!

لذلك، إذا كنت أرغب في الحصول على sitemapnode لكل مقالة من المقالات البالغ عددها 10000 مقالة على صفحتي، فمثلًا:

  • 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

هل هناك نوع من تعيين Wildcard يمكنني القيام به باستخدام خريطة الموقع لمطابقة أي شيء ضمن المقالات؟

أو ربما في صفحة نماذج الويب الخاصة بي، هل هناك طريقة لتعيين العقدة الحالية يدويًا؟

لقد وجدت "القليل" من المساعدة في هذه الصفحة عند القيام بذلك باستخدام ASP.Net MVC Framework، ولكنك لا تزال تبحث عن حل جيد لنماذج الويب.

أعتقد أن ما سأقوم به هو إنشاء موفر SiteMap مخصص

هل كانت مفيدة؟

المحلول

وهذا رداً على التعليق أعلاه.لا يمكنني نشر الكود الكامل، ولكن هذه هي الطريقة الأساسية التي يعمل بها مزود الخدمة الخاص بي.

افترض أن لديك صفحة Article.aspx، وتستخدم معلمة سلسلة الاستعلام "id" لاسترداد عنوان المقالة ونصها وعرضهما.ثم هذا في Web.sitemap:

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

ثم تقوم بإنشاء هذه الفئة:

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);
    }
  }
}

وأخيرًا، يمكنك استخدام هذا الموفر في التعليمات البرمجية الخاصة بك تمامًا كما تستخدم الموفر الثابت.

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

صفي أكثر تعقيدًا من هذا، لكن هذه هي الأساسيات.بدلاً من استخدام معلمة سلسلة الاستعلام، يمكنك فقط تحليل عنوان URL المألوف الذي تستخدمه، واستخدامه بدلاً من ذلك لاسترداد المحتوى الصحيح.لتقليل عمليات البحث الإضافية في قاعدة البيانات مع كل طلب، يمكنك إضافة آلية تخزين مؤقت إلى الموفر (عادةً لن يتغير عنوان المقالة كثيرًا).

أتمنى أن يساعدك هذا.

نصائح أخرى

أعتقد أن هذه ليست إجابة كاملة لسؤالك، ولكنها ربما تعطيك فكرة.لقد كتبت ذات مرة فئة DynamicSiteMapPath وراثة SiteMapPath.أستخدم سمة مخصصة في كل منها <siteMapNode> علامة في Web.sitemap، مثل هذا:

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

ثم تحصل فئة DynamicSiteMapPath على قيمة المعلمة "id"، وتسترد المحتوى من قاعدة البيانات، وتتجاوز عقدة عنصر خريطة الموقع المعروضة حاليًا بالعنوان والرابط الصحيحين.سيستغرق الأمر القليل من العمل، ولكن عند القيام به بشكل صحيح، فهذه طريقة رائعة جدًا لتوفير دعم ديناميكي للصفحة.

لقد واجهت هذه المشكلة وبصراحة لم أجد أي حل أسعدني...لذلك أستعير أفكاراً من هنا وهناك.الحل الخاص بي متعدد الأجزاء:أ) اطلب من SiteMapProvider العثور على الصفحة الفعلية التي تتعامل مع الطلب واستخدام العقدة الخاصة بها، وب) استخدم التقنيات القياسية لتحديث Sitemapnode من هناك.

أ) المشكلة التي كنت أواجهها دائمًا هي أنه إذا لم يكن لدي المسار الظاهري الصحيح، فإن SiteMap.CurrentNode سيكون فارغًا ويتم تنشيط وظيفة SiteMapResolve.لحل هذه المشكلة، قمت بتصنيف XmlSiteMapProvider إلى فئة فرعية وتجاوزت 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;
            }
        }
    }
}

بشكل أساسي، إذا لم يعثر التطبيق الافتراضي على أي شيء، فابحث عن المسار (إن وجد) وحاول العثور على العقدة باستخدام المسار الظاهري للمعالج.

كمرجع هنا جزء من ملفات Web.Config وGlobal.asax وSiteMap:

إضافة المزود

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

الطريق:

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

وخريطة الموقع:

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

ب) أنا فئة فرعية System.Web.UI.Page، تحمل اسم BaseClass، والتي تضيف طريقة لتسجيل المعالجات لحدث 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;
    }

ما زلت بحاجة إلى تعيين عناوين URL بشكل مناسب (سيستخدم عنوان URL للصفحة التي تتلقى المسار)، وهي معلومات بدون توجيه.من المحتمل أن أستخدم سمة مخصصة في خريطة الموقع لإخبار العقدة بكيفية عرض عنوان URL.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top