تهیه خروجی RSS در برنامه‌های ASP.NET MVC
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: چهار دقیقه

در این مطلب با کتابخانه تهیه شده جهت تولید فیدهای RSS سایت جاری آشنا خواهید شد. در این کتابخانه مسایل زیر لحاظ شده است:
1) تهیه یک ActionResult جدید به نام FeedResult برای سازگاری و یکپارچگی بهتر با ASP.NET MVC
2) اعمال زبان فارسی به خروجی نهایی (این مورد حداقل در IE محترم شمرده می‌شود و فید را، راست به چپ نمایش می‌دهد)
3) اعمال جهت‌های rtl و ltr به متون فارسی یا انگلیسی به صورت خودکار؛ به نحوی که خروجی نهایی در تمام فیدخوان‌ها یکسان به نظر می‌رسد.
4) اعمال کاراکتر یونیکد RLE به صورت خودکار به عناوین فارسی (این مساله سبب می‌شود تا عنوان‌های ترکیبی متشکل از حروف و کلمات فارسی و انگلیسی، در فیدخوان‌هایی که متون را، راست به چپ نمایش نمی‌دهند، صحیح و بدون مشکل نمایش داده شود.)
5) نیازی به کتابخانه اضافی خاصی ندارد و پایه آن فضای نام System.ServiceModel.Syndication دات نت است.
6) تنظیم صحیح ContentEncoding و ContentType جهت نمایش بدون مشکل متون فارسی

سورس کامل این کتابخانه به همراه یک مثال استفاده از آن را از اینجا می‌توانید دریافت کنید:

توضیحاتی در مورد نحوه استفاده از آن

کتابخانه کمکی MvcRssHelper به صورت یک پروژه Class library جدا تهیه شده است. بنابراین تنها کافی است ارجاعی را به اسمبلی آن به پروژه خود اضافه کنید. البته این پروژه برای MVC4 کامپایل شده است؛ اما با MVC3 هم قابل کامپایل است. فقط باید ارجاع به اسمبلی System.Web.Mvc.dll را حذف و نمونه MVC3 آن‌را جایگزین کنید.
پس از اضافه کردن ارجاعی به اسمبلی آن، اکشن متد فید شما یک چنین امضایی را باید بازگشت دهد:
 FeedResult(string feedTitle, IList<FeedItem> rssItems, string language = "fa-IR")
آیتم اول، نام فید است. مورد دوم، لیست عناوینی است که قرار است در فید ظاهر شوند. برای مثال، هر بار 20 آیتم آخر مطالب سایت را گزارش‌گیری کرده و به فرمت لیستی از FeedItemها باید ارائه دهید. FeedItem هم یک چنین ساختاری دارد و در اسمبلی MvcRssHelper قرار گرفته:
using System;

namespace MvcRssHelper
{
    public class FeedItem
    {
        public string Title { set; get; }
        public string AuthorName { set; get; }
        public string Content { set; get; }
        public string Url { set; get; }
        public DateTime LastUpdatedTime { set; get; }
    }
}
دو نکته در اینجا حائز اهمیت است:
الف) تاریخ استاندارد یک فید میلادی است نه شمسی. به همین جهت DateTime در اینجا ظاهر شده است.
ب) Url آدرسی است به مطلب متناظر در سایت و باید یک آدرس مطلق مثلا شروع شده با http باشد.


یک مثال از استفاده آن

فرض کنید مدل مطالب سایت ما به نحو زیر است:
using System;

namespace MvcRssApplication.Models
{
    public class Post
    {
        public int Id { set; get; }
        public string Title { set; get; }
        public string AuthorName { set; get; }
        public string Body { set; get; }
        public DateTime Date { set; get; }
    }
}
و یک منبع داده فرضی (کوئری از بانک اطلاعاتی یا استفاده از یک ORM یا ... موارد دیگر) نهایتا تعدادی رکورد را در اختیار ما خواهد گذاشت:
using System;
using System.Collections.Generic;
using MvcRssApplication.Models;

namespace MvcRssApplication.DataSource
{
    public static class BlogItems
    {
        public static IList<Post> GetLastBlogPostsList()
        {
            var results = new List<Post>();
            for (int i = 1; i < 21; i++)
            {
                results.Add(new Post
                {
                     AuthorName = "شخص " + i,
                     Body = "مطلب " + i,
                     Date = DateTime.Now.AddDays(-i),
                     Id = i,
                     Title = "عنوان "+i
                });
            }
            return results;
        }
    }
}
اکنون برای نمایش این اطلاعات به صورت یک فید، تنها کافی است به صورت زیر عمل کنیم:
using System.Collections.Generic;
using System.Web.Mvc;
using MvcRssApplication.DataSource;
using MvcRssApplication.Models;
using MvcRssHelper;

namespace MvcRssApplication.Controllers
{
    public class HomeController : Controller
    {
        const int Min15 = 900;

        [OutputCache(Duration = Min15)]
        public ActionResult Index()
        {
            var list = BlogItems.GetLastBlogPostsList();
            var feedItemsList = mapPostsToFeedItems(list);
            return new FeedResult("فید مطالب سایت ما", feedItemsList);
        }

        private List<FeedItem> mapPostsToFeedItems(IList<Post> list)
        {
            var feedItemsList = new List<FeedItem>();
            foreach (var item in list)
            {
                feedItemsList.Add(new FeedItem
                {
                    AuthorName = item.AuthorName,
                    Content = item.Body,
                    LastUpdatedTime = item.Date,
                    Title = item.Title,
                    //این آدرس باید مطلق باشد به نحو زیر
                    Url = this.Url.Action(actionName: "Details", controllerName: "Post", routeValues: new { id = item.Id }, protocol: "http")
                });
            }
            return feedItemsList;
        }
    }
}
توضیحات
BlogItems.GetLastBlogPostsList منبع داده فرضی ما است. در ادامه باید این اطلاعات را به صورت لیستی از FeedItemها در آوریم. می‌توانید از AutoMapper استفاده کنید یا در این مثال ساده، نحوه انجام کار را در متد mapPostsToFeedItems ملاحظه می‌کنید.
نکته مهم بکارگرفته شده در متد mapPostsToFeedItems، استفاده از Url.Action برای تولید آدرس‌هایی مطلق متناظر با کنترلر نمایش مطالب سایت است.
پس از اینکه feedItemsList نهایی به صورت پویا تهیه شد، تنها کافی است  return new FeedResult را به نحوی که ملاحظه می‌کنید فراخوانی کنیم تا خروجی حاصل به صورت یک فید RSS نمایش داده شود و قابل استفاده باشد. ضمنا جهت کاهش بار سرور می‌توان از OutputCache نیز به مدتی مشخص استفاده کرد.
  • #
    ‫۱۲ سال و ۱ ماه قبل، دوشنبه ۲۰ شهریور ۱۳۹۱، ساعت ۲۳:۳۸
    سلام. بسیار کاربردی و عالی. سپاس.
  • #
    ‫۱۲ سال و ۱ ماه قبل، سه‌شنبه ۲۱ شهریور ۱۳۹۱، ساعت ۰۵:۰۳
    یک‌سری از وبگاه‌ها عادت دارن از description به‌جای content استفاده کنند.آیا این کتابخانه این قابلیت رو داره؟
    • #
      ‫۱۲ سال و ۱ ماه قبل، سه‌شنبه ۲۱ شهریور ۱۳۹۱، ساعت ۰۵:۱۳
      خروجی کتابخانه فوق، RSS استاندارد است و description دارد. مقادیر خواص کلاس FeedItem نهایتا به این خروجی نگاشت می‌شود.
      برای نمونه این خروجی رو می‌تونید در سورس نهایی فید سایت مشاهده کنید.
  • #
    ‫۱۲ سال و ۱ ماه قبل، سه‌شنبه ۲۱ شهریور ۱۳۹۱، ساعت ۱۵:۰۰
    ممنون آقای نصیری. بسیار عالی بود و ابهامات زیادی در مورد Rss برای من برطرف شد.

  • #
    ‫۱۲ سال و ۱ ماه قبل، پنجشنبه ۲۳ شهریور ۱۳۹۱، ساعت ۱۹:۵۴
    در صورت امکان در مورد نحوه استفاده از کتابخانه MvcRssHelper در پروژه‌های ASP.NET و تغییراتی که باید در این کتابخانه انجام شود، راهنمایی کنید. با تشکر 
    • #
      ‫۱۲ سال و ۱ ماه قبل، پنجشنبه ۲۳ شهریور ۱۳۹۱، ساعت ۲۰:۵۲
      آنچنان تفاوتی نداره. فقط اینبار باید از فایل‌های ashx استفاده کنید. روال ProcessRequest آن معادل روال ExecuteResult موجود در فایل FeedResult.cs است.
  • #
    ‫۱۱ سال و ۱۲ ماه قبل، شنبه ۲۲ مهر ۱۳۹۱، ساعت ۲۲:۳۹
    سلام
    ممنوم بابت مطلب خوبتون
    ولی فایل که برای دانلود گذاشتید مشکل داره
    پروژه ام وی سی توش نیست ... ممنونم می‌شم اگر اصلاح کنید
    • #
      ‫۱۱ سال و ۱۲ ماه قبل، شنبه ۲۲ مهر ۱۳۹۱، ساعت ۲۳:۱۱
      داخل فایل MvcRssApplication.zip فوق این موارد هست:
      پوشه MvcRssApplication : یک پروژه مثال
      پوشه MvcRssHelper : کتابخانه اصلی
      • #
        ‫۱۱ سال و ۱۲ ماه قبل، یکشنبه ۲۳ مهر ۱۳۹۱، ساعت ۱۸:۵۲
        سلام، من هم توی لود پروژه مشکل دارم، البته همه نسخه‌های mvc رو نصب شده داشتم ولی:


        • #
          ‫۱۱ سال و ۱۲ ماه قبل، یکشنبه ۲۳ مهر ۱۳۹۱، ساعت ۱۹:۵۶
          - این یک پروژه MVC4 است. همچنین فرض هم بر این است که IIS Express بر روی سیستم شما نصب است (^).
  • #
    ‫۱۱ سال و ۱۲ ماه قبل، یکشنبه ۳۰ مهر ۱۳۹۱، ساعت ۰۳:۴۱
    نسخه به روز شده این پروژه:
    MvcRssApplication.zip

    تغییرات:
    پیشتر فقط تاریخ به روز رسانی را داشت:
    <a10:updated>2012-10-20T16:09:13+03:30</a10:updated>
    الان تاریخ انتشار هم به آن اضافه شده:
    <pubDate>Sat, 30 Jan 2010 02:26:32 -0800</pubDate>


    • #
      ‫۱۱ سال و ۱۱ ماه قبل، چهارشنبه ۳ آبان ۱۳۹۱، ساعت ۰۲:۳۷
      به روز رسانی سوم:
      MvcRssApplication3.zip

      تغییرات (بر اساس نظرات  W3C Feed Validation Service ):
      - channel link به آن اضافه شد.
      - فضای نام a10 ایی که تولید می‌شد با atom جایگزین شد.
      • #
        ‫۱۱ سال و ۱۱ ماه قبل، شنبه ۱۳ آبان ۱۳۹۱، ساعت ۲۰:۳۳
        سلام

        از این روش می‌شه برای ساخت sitemap  هم استفاده کرد؟
        اگر نه چطور؟
  • #
    ‫۹ سال و ۶ ماه قبل، دوشنبه ۱۰ فروردین ۱۳۹۴، ساعت ۰۶:۲۵
    یک نکته‌ی تکمیلی
    فید سایت امروز از کار افتاده بود. علت آن وجود یک سری کاراکتر غیرمجاز XML در متن بود که باید به نحو ذیل پاک شوند:
            private static readonly Regex _matchHexadecimalSymbols =
                new Regex("[\x00-\x08\x0B\x0C\x0E-\x1F]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
    
            /// <summary>
            /// there are a lot of symbols which can't be in xml code.
            /// </summary>
            public static string RemoveHexadecimalSymbols(this string txt)
            {
                return string.IsNullOrWhiteSpace(txt) ?
                    string.Empty : _matchHexadecimalSymbols.Replace(txt, string.Empty);
            }
    در کدهای مطلب فوق، مقادیر content و title باید پیش از استفاده، توسط این متد پاکسازی شوند.
  • #
    ‫۹ سال و ۵ ماه قبل، دوشنبه ۳۱ فروردین ۱۳۹۴، ساعت ۰۳:۵۱
    خیلی متشکر، کدها بسیار کار امد بود و بدون دردسر در پروژه جواب داد 
    فقط این که مثلا باید ادرس http://localhost:40252/feed/rss  را وارد کرد ، حال این شکل rss  (مربع نارنجی قرمز بالا چپ ادرس بار در گوگل کروم)که در نوار ابزار نمایش داده میشود رو چه تغییراتی باید انجام بدهم تا در ادرس بار نمایش داده شود ؟
    • #
      ‫۹ سال و ۵ ماه قبل، دوشنبه ۳۱ فروردین ۱۳۹۴، ساعت ۰۴:۵۷
      به هدر صفحه باید این مورد جهت فعال سازی auto discovery اضافه شود:
      <link title="فید آخرین تغییرات سایت" href="/rss.xml" type="application/rss+xml" rel="alternate" />
      محدودیتی هم ندارد. هر تعدادی که نیاز است.
  • #
    ‫۶ سال و ۵ ماه قبل، چهارشنبه ۲۹ فروردین ۱۳۹۷، ساعت ۱۸:۲۴
    معادل این مطلب در برنامه‌های ASP.NET Core

    ابتدا بسته‌ی نیوگت DNTCommon.Web.Core را نصب کنید:
    PM> Install-Package DNTCommon.Web.Core
    سپس مثالی از FeedResult آن‌را در اینجا می‌توانید مشاهده کنید.
    • #
      ‫۵ سال و ۱۰ ماه قبل، پنجشنبه ۱۰ آبان ۱۳۹۷، ساعت ۲۲:۱۲
      منظور از دو فیلد زیر چیه و چه کاربردی دارن؟ مثالی از نحوه مقداردهی این دو فیلد میشه ارائه بدید
                      FeedImageContentPath = "",
                      FeedImageTitle = "",

      • #
        ‫۵ سال و ۱۰ ماه قبل، پنجشنبه ۱۰ آبان ۱۳۹۷، ساعت ۲۳:۲۱
        جهت نمایش لوگوی سایت شما در یک فید خوان است. FeedImageContentPath، مسیر نسبی به یک تصویر در سایت شما است (content/logo.jpg/~) و FeedImageTitle توضیحات آن. این مسیر نسبی به صورت خودکار به مسیر مطلق تبدیل می‌شود.