تولید SiteMap استاندارد و ایجاد یک ActionResult اختصاصی برای Return کردن SiteMap تولید شده
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: سه دقیقه

یکی از item‌های مهم در بهینه سازی SEO یک وب‌سایت وجود یک SiteMap استاندارد متشکل از لینک‌های موجود در سایت هست که در وب‌سایت‌های داینامیک معمولا این لینک‌ها بر اساس داده‌های موجود در بانک اطلاعاتی ایجاد میشه. برای مثال مطالب، اخبار و ....
در اینجا بنده قبلا یک کلاس برای تولید SiteMap آماده کردم که در پروژه‌های خودم ازش استفاده میکنم. توسط این کلاس میتونید به صورت داینامیک SiteMap وب‌سایت مبتنی بر ASP.NET MVC خودتون رو ایجاد کنید.

برای آشنایی با ساختار یک SiteMap استاندارد میتونید به لینک رسمی روبرو مراجعه کنید : http://www.sitemaps.org/de/protocol.html 

بنده کلاس‌های زیر رو بر مبنای لینک مذکور در سایت رسمی SiteMaps تولید کردم.  بعد از تولید SiteMap نیاز دارید که اون رو مثلا به عنوان خروجی یک ActionResult بازگردونید. برای این کار هم یک کلاس با نام XmlResult  مشتق شده از ActionResult آماده سازی کردم که کلاس تولید شده SiteMap رو Serialize میکنه و به عنوان نتیجه‌ی یک Action باز می‌گردونه .
using System;
using System.Collections;
using System.Web.Mvc;
using System.Xml.Serialization;

namespace Neoox.Core.SeoTools
{
    [XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
    public class Sitemap
    {
        private ArrayList map;

        public Sitemap()
        {
            map = new ArrayList();
        }

        [XmlElement("url")]
        public Location[] Locations
        {
            get
            {
                Location[] items = new Location[map.Count];
                map.CopyTo(items);
                return items;
            }
            set
            {
                if (value == null)
                    return;
                Location[] items = (Location[])value;
                map.Clear();
                foreach (Location item in items)
                    map.Add(item);
            }
        }

        public int Add(Location item)
        {
            return map.Add(item);
        }
    }

    public class Location
    {
        public enum eChangeFrequency
        {
            always,
            hourly,
            daily,
            weekly,
            monthly,
            yearly,
            never
        }

        [XmlElement("loc")]
        public string Url { get; set; }

        [XmlElement("changefreq")]
        public eChangeFrequency? ChangeFrequency { get; set; }
        public bool ShouldSerializeChangeFrequency() { return ChangeFrequency.HasValue; }

        [XmlElement("lastmod")]
        public DateTime? LastModified { get; set; }
        public bool ShouldSerializeLastModified() { return LastModified.HasValue; }

        [XmlElement("priority")]
        public double? Priority { get; set; }
        public bool ShouldSerializePriority() { return Priority.HasValue; }
    }

    public class XmlResult : ActionResult
    {
        private object objectToSerialize;

        public XmlResult(object objectToSerialize)
        {
            this.objectToSerialize = objectToSerialize;
        }

        public object ObjectToSerialize
        {
            get { return this.objectToSerialize; }
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (this.objectToSerialize != null)
            {
                context.HttpContext.Response.Clear();
                var xs = new System.Xml.Serialization.XmlSerializer(this.objectToSerialize.GetType());
                context.HttpContext.Response.ContentType = "text/xml";
                xs.Serialize(context.HttpContext.Response.Output, this.objectToSerialize);
            }
        }
    }
}
 و اما نحوه استفاده از این کلاس‌ها هم خیلی سادست. به مثال زیر توجه کنید ... فقط این نکته رو در نظر داشته باشید که item هایی که به sitemap اضافه میشه واکشی شده از بانک اطلاعاتی هست، در این مثال چون خواستم ساده توضیح داده بشه نحوه استفاده از این کلاس‌ها، این داده‌ها به صورت static در نظر گرفته شد ولی شما میتونید داده‌ها رو بر اساس ساختار بانک اطلاعاتی خودتون واکشی کرده و به SiteMap اضافه کنید تا یک SiteMap کاملا پویا و Dynamic داشته باشید...
        public ActionResult Sitemap()
        {
            Sitemap sm = new Sitemap();
            sm.Add(new Location()
            {
                Url = string.Format("http://www.TechnoDesign.ir/Articles/{0}/{1}", 1, "SEO-in-ASP.NET-MVC"),
                LastModified = DateTime.UtcNow,
                Priority = 0.5D
            });
            return new XmlResult(sm);
        }
  • #
    ‫۱۱ سال و ۴ ماه قبل، چهارشنبه ۱ خرداد ۱۳۹۲، ساعت ۱۹:۰۹
    یک نکته تکمیلی:
    ایجاد خودکار آدرس sitemap.xml از روی آدرس کنترلر SiteMap با افزودن مسیریابی مرتبط با آن: (در حقیقت ایجاد آدرس، برای فایلی که وجود خارجی ندارد و نگاشت آن به یک کنترلر و اکشن متد خاصی در آن)
    routes.MapRoute(
                    "SiteMap_route", // Route name
                    "sitemap.xml", // URL with parameters
                    new { controller = "Sitemap", action = "index", name = UrlParameter.Optional, area = "" } // Parameter defaults
                );
    • #
      ‫۱۱ سال و ۴ ماه قبل، چهارشنبه ۱ خرداد ۱۳۹۲، ساعت ۱۹:۲۶
      این کار که 100% باید انجام بشه وگرنه بی فایدست تمام ماجرا . ممنون از آقای نصیری بابت پیوست این نکته. دوستان حتما توجه داشته باشن ....
    • #
      ‫۱۰ سال و ۵ ماه قبل، جمعه ۵ اردیبهشت ۱۳۹۳، ساعت ۱۹:۰۹
      با سلام. آقای نصیری ممنون میشم در مورد این نکته ای که فرمودید بیشتر توضیح بدید.
      ممنونم
  • #
    ‫۱۱ سال و ۴ ماه قبل، چهارشنبه ۱ خرداد ۱۳۹۲، ساعت ۲۱:۱۱
    in robots.txt file:
    Sitemap: http://www.site.com/Sitemap
    علاوه بر نکته فوق باید در فایل robots.txt سایت هم یک سطر با آدرس مطلق (و نه نسبی) به مسیر سایت‌مپ اشاره کنه تا موتورهای جستجو بدونند کجا رو باید بررسی کنند
  • #
    ‫۱۱ سال و ۱ ماه قبل، سه‌شنبه ۲۹ مرداد ۱۳۹۲، ساعت ۰۲:۴۹
    با سلام؛ چند سوال داشتم:
    1- به نظرتون اگر تعداد صفحات وب سایت زیاد باشه این کار (ساخت sitemap به ازای هر درخواست) رو سرور فشار ایجاد نمی‌کنه؟
    2 -همان طور که می‌دونید حداکثر می‌شود 50000 هزار لینک در یک sitemap  قرار داد و به ازای مقادیر بیشتر باید چندین sitemap ایجاد کرد. 
    برای این سناریو چطور می‌شه رفتار کرد؟
    3- و سوال آخر اینکه چرا آقای نصیری لینک‌های محدودی را در sitemap  سایت قرار داده اند؟ دلیل خاصی داشته است؟
    • #
      ‫۱۱ سال و ۱ ماه قبل، سه‌شنبه ۲۹ مرداد ۱۳۹۲، ساعت ۰۲:۵۸
      1 - از OutputCache حتما باید استفاده کنید.
      2 و 3 - موتورهای جستجو به دنبال لینک‌های جدید در سایت شما هستند. زمانیکه موارد قبلی ایندکس شدند و در بانک اطلاعاتی آن‌ها موجودند، فقط موارد جدیدتر را در سایت مپ قرار بدید. وجود موارد قدیمی ایندکس شده مهم نیستند و مدام چک خواهند شد (جهت بررسی صحت اطلاعات بانک اطلاعاتی موتورهای جستجو).
      این مورد را اگر خواستید بررسی کنید، از ابزار وب مستر گوگل بهره بگیرد. هر روز آمار می‌دهد، چه مواردی کلا ایندکس شده (همچنین چه تعدادی دقیقا از طریق سایت مپ ایندکس شده)، چه مشکلاتی داشته، موارد قدیمی که در بانک اطلاعاتی آن هست و در سایت شما یافت نشده، کدام‌ها هستند و غیره.

      • #
        ‫۱۱ سال و ۱ ماه قبل، سه‌شنبه ۲۹ مرداد ۱۳۹۲، ساعت ۲۲:۵۲
        تشکر بابت پاسختون
        2 - سایتی که من بر روی وب می‌گذارم با حدود یک میلیون صفحه در وب قرار می‌گیرد! (و قابل ذکر هست که بیش از 50000 لینک در سایت مپ ممکن نیست) بر اساس مواردی که شما بیان کردید، باید هر روز مقداری از این لینک‌ها را در سایت مپ قرار بدهم و بعد از ایندکس شدن توسط گوگل آن‌ها را تغییر دهم که عملا برای این حجم بالا ممکن نیست.
        می تونم بپرسم جرا با ساختن فایل‌های فیزیکی برای سایت مپ موافق نیستید؟
        (البته در شرایط صورت مسئله ای که بیان کردم) در این صورت می‌شود طوری برنامه ریزی کرد که این فایل ها( به دلیل بالا بودن تعداد لینک از چندین فایل استفاده شود) در بازه زمانی مشخص دوباره باز سازی شوند و هیچ بار اضافه ای برای ایجاد هرباره آن‌ها به وجود نیاید.
        باز هم تشکر بابت وقتی که می‌گذارید...
        • #
          ‫۱۱ سال و ۱ ماه قبل، سه‌شنبه ۲۹ مرداد ۱۳۹۲، ساعت ۲۳:۱۵
          کش کردن یک روش است برای کاهش ساخت خروجی پویا به ازای هر درخواست (سؤال مطرح شده) و از آن برداشت نمی‌شود که روش‌های دیگر خوب هستند یا خیر.
      • #
        ‫۱۰ سال و ۸ ماه قبل، چهارشنبه ۲۳ بهمن ۱۳۹۲، ساعت ۱۳:۵۳
        سلام امکان استفاده این در ASP.NET Web forms هست چون من میخوام این کارو با استفاده از یک httphandler بکنم ؟
        • #
          ‫۱۰ سال و ۸ ماه قبل، چهارشنبه ۲۳ بهمن ۱۳۹۲، ساعت ۱۳:۵۸
          بله. مفاهیم و کدهای XmlResult تهیه شده را مستقیما در یک فایل ashx هم می‌شود بکار برد. context مورد استفاده، قابل انتقال است.
  • #
    ‫۱۱ سال و ۱ ماه قبل، سه‌شنبه ۲۹ مرداد ۱۳۹۲، ساعت ۲۳:۱۲
    و البته سوال دیگه هم که داشتم اینکه: 
    من از همین Routing  که شما توی کامنت اول بیان کردید استفاده کردم. ( که طبیعتا درسته ) ولی توی پروژه بنده IIS  ایرور می‌ده که این فایل (sitemap.xml)رو پیدا نکرده! فکر می‌کنم عمل routing  به درستی انجام نمی‌شه.
    من از mvc4 در vs2102 استفاده می‌کنم.
      • #
        ‫۱۰ سال و ۱۱ ماه قبل، شنبه ۴ آبان ۱۳۹۲، ساعت ۲۰:۰۷
        منم رفتم اون مطالبو خوندم ولی چیزی دستگیرم نشد .و هنوز همین مشکلو داردم. نمیشه بیشتر راهنمایی کنین؟
        • #
          ‫۱۰ سال و ۱۱ ماه قبل، شنبه ۴ آبان ۱۳۹۲، ساعت ۲۰:۲۰
          Route سفارشی زمانی عمل می‌کنه که قبل از Route پیش فرض تعریف شود. route پیش فرض اصطلاحا catch all است و نوبت به بقیه نخواهد رسید.
          • #
            ‫۱۰ سال و ۱۱ ماه قبل، شنبه ۴ آبان ۱۳۹۲، ساعت ۲۱:۲۹
            ایییییییییییییییییول...! خیلی باحالین. دقیقا مشکل همین بود . ممنون.
  • #
    ‫۱۰ سال و ۱ ماه قبل، چهارشنبه ۲۲ مرداد ۱۳۹۳، ساعت ۲۰:۰۳
    سلام .خیلی ممنون به خاطر مطالبتون.
    میخواستم بدونم در چه زمان و در کجا باید این Action  رو صدا بزنیم.
    با تشکر
    • #
      ‫۱۰ سال و ۱ ماه قبل، چهارشنبه ۲۲ مرداد ۱۳۹۳، ساعت ۲۰:۰۹
      موتورهای جستجو بر اساس تنظیمات فایل robots.txt قرار است آن‌را یافته و صدا بزنند. کاربرد شخصی ندارد.
  • #
    ‫۹ سال و ۱۲ ماه قبل، سه‌شنبه ۱ مهر ۱۳۹۳، ساعت ۰۱:۵۶
    سلام
    چه جوری میشه از این کلاس توی asp.net webform استفاده کرد؟
    اگه میشه نحوه استفاده از این کد‌ها رو توی webform بذارید. ممنون
    • #
      ‫۹ سال و ۱۲ ماه قبل، سه‌شنبه ۱ مهر ۱۳۹۳، ساعت ۰۲:۳۰
      اکثر کدهای آن یکی است منهای کلاس XmlResult آن.
      برای پیاده سازی و جایگزینی آن در وب فرم‌ها یک Generic handler استاندارد را اضافه کنید و در متد ProcessRequest آن، کدهای متد ExecuteResult فوق را قرار دهید.
       public void ProcessRequest (HttpContext context)
      البته چون در اینجا HttpContext را مستقیما دارید، قسمت‌های context.HttpContext متد ExecuteResult   می‌شوند context.
      Sitemap_ashx.cs
  • #
    ‫۹ سال و ۱۱ ماه قبل، دوشنبه ۱۹ آبان ۱۳۹۳، ساعت ۱۵:۴۰
    با تشکر
    آیا راهی وجود داره بدون تعریف کردن route بتوان به اکشن مورد نظر دسترسی پیدا کرد؟
    چون برای فعال کردن این قابلیت باید اجازه وارد کردن dot در url رو داد که برامون امکان پذیر نیست
    • #
      ‫۹ سال و ۱۱ ماه قبل، دوشنبه ۱۹ آبان ۱۳۹۳، ساعت ۱۵:۴۵
      کمی بالاتر در نظرات عنوان شده، موتورهای جستجو این مسیر را (هر آدرسی با هر شکل یا نامی که دارد؛ مهم نیست) صرفا از فایل robots.txt دریافت می‌کنند.
  • #
    ‫۹ سال و ۸ ماه قبل، دوشنبه ۱۳ بهمن ۱۳۹۳، ساعت ۰۴:۳۷
    سلام؛ عالی بود. من برای خواندن از بانک اطلاعاتی این کد رو نوشتم
     public virtual ActionResult Sitemap()
            {
                var data = new sunn.Models.ApplicationDbContext().Posts.ToList();
                SiteMap sm = new SiteMap();
                foreach (var siteno in data)
                {
                    sm.Add(new Location()
                       {
                           Url = string.Format("http://www.MySite.ir/Develop/Home/Post/{0}", siteno.Id),
                           LastModified = siteno.InsertDate,
                           Priority = 0.5D
                       });
                }
    
                return new XmlResult(sm);
            }
    زمانیکه در آدرس بار نام این اکشن رو میزنم، تمامی اطلاعات رو نشون میده؛ اما بدون هیچ فرمتی و پشت سر هم. اما ViewSource رو که میزنم توی source کاملا نقشه سایت رو نشون میده .

    دو تا سوال : اول اینکه به چه نحوی میتونم آدرس فایل xml  را بدست بیارم که مثلاً به گوگل معرفی کنم و دوم اینکه به جای نمایش این صفحه ناخوانا بتوانم یک صفحه خوانا‌تر با فرمت نمایش بدم
    • #
      ‫۹ سال و ۸ ماه قبل، دوشنبه ۱۳ بهمن ۱۳۹۳، ساعت ۰۴:۴۸

      خوانایی این خروجی اهمیتی نداره چون برای ماشین درست میشه نه برای انسان. فرمت هم نداشته باشه بهتره چون حجم کمتری رو به خودش اختصاص می‌ده. ولی در کل باید خاصیت Indent تنظیم بشه، در صورت نیاز.

      در مورد خروجی با پسوند xml هم باید مسیریابی جدید اضافه کنی که قبلا در نظرات همین بحث مطرح شده (اولین نظر به علاوه مورد robots.txt که در نظرات بعدی هست).

  • #
    ‫۸ سال و ۱۲ ماه قبل، سه‌شنبه ۳۱ شهریور ۱۳۹۴، ساعت ۱۵:۲۲
    با سلام و تشکر
    بعد از مطالعه چندین مورد آموزشی در باره siteMap یه مشکل مفهومی تو پیاده سازی دارم .
    فرض کنید 2 بخش تو سایت دارم . محصولات و مقالات
    تعداد محصولاتم امروز 10 تاست و مقالات 50 تا. آیا من باید 2 تا SiteMap به ازای این دو بخش داشته باشم یا فقط یکی و لینک‌ها رو به صورت مختلط توش ایجاد کنم؟ اگه فقط یک sitemap باشه اونوقت زمانی که تعداد بخش‌ها زیاد باشه و لینک‌ها هم هر روز افزوده بشه اونوقت به یه sitemap نا منظم نمیرسیم؟
    راهکاری براش هست؟
    من یه سر به sitemap سایتی زدم . یه sitemap روت داره که توش لینک‌های sitemap‌های هر بخش هست و برا هر بخش اومده sitemap خودش رو ایجاد کرده! چطور اینکاره کرده؟
    نکته دیگه ای که هست اینکه آیا من باید یه جدول برای sitemapایجاد کنم و لینک هایی که مثلا امروز ایجاد شده رو توش درج کنم و هر وقت لینکی اضافه یا حذف شد بیام جدول و آپدیت کنم و بعدش ازش یه sitemap درست کنم؟
    یه جا خونده بودم که زمانی که sitemap توسط Google ایندکس میشه نباید دوباره لینک‌های تکراری در دفعات بعدی توش وجود داشته باشه. اینو چطور میشه مدیریت کرد؟ ممنون
    • #
      ‫۸ سال و ۱۲ ماه قبل، سه‌شنبه ۳۱ شهریور ۱۳۹۴، ساعت ۱۶:۰۶
      - قسمت‌های مختلف را کوئری می‌گیرید (یعنی به صورت پویا تولید می‌شود و نه اینکه جایی ثبت شوند)، union می‌کنید (چندین قسمت هست؟ مهم نیست. لیست‌های تمام آن‌ها باید به فرمت Sitemap نگاشت شده و یکی شوند) و نهایتا به صورت یک خروجی واحد ارائه می‌دهید. بحث لینک‌های تکراری در اینجا مهم نیست (و مرتبط است به محتوای تکراری با آدرس‌های مختلف در یک سایت و نه لینک‌های سایت‌مپ). ممکن هست یک سایت در طول هفته اصلا رکورد جدیدی نداشته باشد. موتور جستجوگری که به آن می‌رسد یک سری لینک مشخص و تکراری را هر روز دریافت می‌کند و مدیریت ثبت آن‌ها هم کاملا مشخص است و خودشان تکراری ثبت نمی‌کنند.
      برای درک بهتر نحوه‌ی ایندکس شدن sitemap نیاز هست به Google Webmaster Tools وب سایت خودتان را اضافه کنید و سپس token آن‌را در سایت معرفی کنید. پس از مدتی می‌توانید گزارش بگیرید که دقیقا چه مواردی را ثبت کرده‌است و به چه نحوی.
      - ضمنا امکان تعریف Sitemap index هم وجود دارد (جهت تعریف چندین سایت‌مپ در سایت). اطلاعات بیشتر در پروتکل آن آماده‌است. ولی در کل فرمت تولید آن سایت‌مپ‌ها هم به همین نحو استاندارد معرفی شده‌است. فقط در این حالت خاص که سایت‌مپ در ریشه‌ی سایت قرار نمی‌گیرد و یا به آن اشاره نمی‌کند، محدود هستید به معرفی لینک‌های همان پوشه و یا بازه.
  • #
    ‫۶ سال و ۵ ماه قبل، چهارشنبه ۲۹ فروردین ۱۳۹۷، ساعت ۱۸:۲۸
    معادل این مطلب در برنامه‌های ASP.NET Core

    ابتدا بسته‌ی نیوگت DNTCommon.Web.Core را نصب کنید:
    PM> Install-Package DNTCommon.Web.Core
    سپس مثالی از SitemapResult آن‌را در اینجا می‌توانید مشاهده کنید.