ساخت RSS/Atom Feed در MVC

در این مقاله با مفهوم RSS/ Atom Feed آشنا می شوید ،ما در اینجا به مقایسه Atom و RSSمی پردازیم.شما در این مقاله یاد می گیرید که چگونه Atom Feed را پیاده سازی کنید و چگونه یک Feedی که ساختید را اعتبارسنجی کنید و...

ساخت RSS/Atom Feed در MVC

RSS/Atom Feed  چیست؟

  RSS/ Atom Feed یک راه خوب برای بروزرسانی سایت برای کاربران می باشد. اساسا، RSS/Atom Feed  فقط یک سندXML  می باشد که به طور مداوم با محتوا و لینک های جدید به روزرسانی می شود.

Feed Reader  های متعددی وجود دارند که به شیوه های مختلفی کار می کنند اما اغلب آن ها Feed ها را از  سایت های مختلف در درون یک Reading list  مستقل جمع آوری می کنند.هنگامی که یک کاربر، سایتFeed شما را پذیرفت و به لیست اشتراک خود اضافه کرد، هر زمان که شما Feed خود را به روزرسانی کنید ،در Reading list کاربر، تمامی محتوای جدید ظاهر می شود.

FeedReaderها در تمامی شکل ها و سایزها می آیند،حتی مرورگرها هم توانایی FeedReading  ابتدایی را دارند.در اینجا  تصویری از  نوار کناریBookMarks  در Firefox   بعد از اضافه کردن فید Visual Studio Magazine ،می باشد(خودتان در Fire fox  این کار را امتحان کنید) .bookmark  زیر فولدر Blogs  هرباری که Feed  به روزرسانی شود ،آن هم به روزرسانی می شود.

وب سایت های FeedReading  مانند Feedly  و NewsBlur   بسیار محبوب هستند. FeedReader  ها درواقع فقط برنامه هایی هستند که در تلفن ها و یا تبلت ها قابل اجرا هستند و همچنین این ها می توانند حتی اطلاعیه ها(notifications) را وقتی که  Feed  تغییر کند ، و یا محتوای جدیدی برای خواندن  داشته باشد، افزایش دهند.سرویس های مانند Feedly  و NewsBlur  برنامه های مختص به خود را دارند.

مقایسه  RSS با   :Atom

آخرین ورژن از Rss ،    2.0می باشد در حالی که ، Atom 1.0می باشد.ورژن  Atom  1.0   استاندارد وب می باشد، ولی Rss  استاندارد وب نمی باشد و درواقع متعلق به دانشگاه هاروارد می باشد.

Atom  به طور خاص برای رسیدگی به مشکلات در RSS   2.0 ایجاد شد وبا فرمت جدیدتر و خیلی بهتر تعریف شده است.هردوی این فرمت ها تا حدودی قدیمی شده اند و توسط استانداردهای وب  از حمایت های گسترده ای برخوردارند. اگر شما قدرت انتخاب در نوع فرمت را داشتید ، به سمت Atom  1.0 بروید.

Atom 1.0 XML

  اگر می خواهید  بدانید  Atom Feed  شبیه به چه چیزی می باشد یک مثال ساده اما کامل در زیر وجود دارد.

<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-GB" xmlns:media="http://search.yahoo.com/mrss/" xmlns="http://www.w3.org/2005/Atom">
  <title type="text">ASP.NET MVC Boilerplate</title>
  <subtitle type="text">This is the ASP.NET MVC Boilerplate feed description.</subtitle>
  <id>3D797739-1DED-4DB8-B60B-1CA52D0AA1A4</id>
  <rights type="text">© 2015 - Rehan Saeed</rights>
  <updated>2015-06-24T15:54:21+01:00</updated>
  <category term="Blog" />
  <logo>http://example.com/icons/atom-logo-96x48.png</logo>
  <author>
    <name>Rehan Saeed</name>
    <uri>http://rehansaeed.com</uri>
    <email>example@email.com</email>
  </author>
  <contributor>
    <name>Rehan Saeed</name>
    <uri>http://rehansaeed.com</uri>
    <email>example@email.com</email>
  </contributor>
  <link rel="self" type="application/atom+xml" href="http://example.com/feed/" />
  <link rel="alternate" type="text/html" href="http://example.com/" />
  <link rel="hub" href="https://pubsubhubbub.appspot.com/" />
  <icon>http://example.com/icons/atom-icon-48x48.png</icon>
  <entry>
    <id>6139F098-2E59-4405-9BC7-0AAB4CF78E23</id>
    <title type="text">Item 1</title>
    <summary type="text">A summary of item 1</summary>
    <published>2015-06-24T15:54:21+01:00</published>
    <updated>2015-06-24T15:54:21+01:00</updated>
    <author>
      <name>Rehan Saeed</name>
      <uri>http://rehansaeed.com</uri>
      <email>example@email.com</email>
    </author>
    <contributor>
      <name>Rehan Saeed</name>
      <uri>http://rehansaeed.com</uri>
      <email>example@email.com</email>
    </contributor>
    <link rel="alternate" type="text/html" href="http://example.com/item1/" />
    <link rel="enclosure" type="image/png" href="http://example.com/item1/atom-icon-48x48.png" />
    <category term="Category 1" />
    <rights type="text">© 2015 - Rehan Saeed</rights>
    <media:thumbnail url="http://example.com/item1/atom-icon-48x48.png" width="48" height="48" />
  </entry>
  <entry>
    <id>927406DD-E8DC-41ED-8154-30DE91B0877A</id>
    <title type="text">Item 2</title>
    <summary type="text">A summary of item 2</summary>
    <published>2015-06-24T15:54:21+01:00</published>
    <updated>2015-06-24T15:54:21+01:00</updated>
    <author>
      <name>Rehan Saeed</name>
      <uri>http://rehansaeed.com</uri>
      <email>example@email.com</email>
    </author>
    <contributor>
      <name>Rehan Saeed</name>
      <uri>http://rehansaeed.com</uri>
      <email>example@email.com</email>
    </contributor>
    <link rel="alternate" type="text/html" href="http://example.com/item2/" />
    <link rel="enclosure" type="image/png" href="http://example.com/item2/atom-icon-48x48.png" />
    <category term="Category 2" />
    <rights type="text">© 2015 - Rehan Saeed</rights>
    <media:thumbnail url="http://example.com/item2/atom-icon-48x48.png" width="48" height="48" />
  </entry>
</feed>

در قسمت root    برای ، XML  ما عنصر Feed  داریم که به ما AtomFeed  را نشان می دهد.که در آن ابرداده هایMeta-Data)  )مختلف  در مورد Feed وجود دارد.که شامل:

Title:عنوان Feed

Subtitle:یک توضیح مختصر  ازFeed

Id: یک Id  واحد(Uniqe)  برای Feed  .هیچ Feed  دیگری در اینترنت نباید  Idیکسانی داشته باشند.

Rights:اطلاعات کپی رایت

Updated:زمان آخرین باری که  Feed  به روزرسانی شده.

Category: تعداد دسته بندی ها( categories)  که می تواند صفر یا بیشتر باشد، که متعلق به Feed  می باشد.

Logo:تصویر گسترده به نسبت 2:1 به نمایندگی از Feed.

Author: صفر یا بیشترتعداد نویسندگان Feed.

Contributor: صفر یا بیشترتعداد حامیان Feed.

link rel=”self”:لینک خود Feed

link rel=”alternate”: لینک جایگزین  به نمایندگی از Feed.

Icon:یک تصویر مربعی به نسبت 1:1 به نمایندگی از Feed.

المان های entry، "چیزهای "واقعی در Feed  شما هستند که در حال توضیح آنها هستید.هر entry دارای  Meta-Data  می باشد که به نظر می رسد بسیار شبیه  Meta-Data یی می باشد که ما برای توصیف خود Feed  استفاده کردیم.

Id: یک شناسه واحد برای entry می باشد. این می تواند Row ID دیتابیس باشد ونیازی نیست که GUID باشد.  

Title: عنوان مطلب entry

Summary: یک خلاصه کوتاه برای آن که هر entry در مورد چه موضوعی می باشد.

Published: زمان انتشار entry

Updated: زمان آخرین تغیر  entry

Author: صفر یا بیشترتعداد نویسندگان entry

Contributor: صفر یا بیشترتعداد حامیان entry

link rel=”alternate”: لینک جایگزین  به نمایندگی از entry

link rel=”enclosure”: یک تصویر به نمایندگی ازentry

category: دسته بندی entry

Rights:برخی از برنامه های کپی رایت

Media:thumbnail  thumbnail یک نماینده از entry میباشد.این افزونه که نوسط یاهو معرفی شد، یک افزونه ی غیر استاندارد برای Atom 1.0 به شمار می رود اما به دلیل کاربرد زیادی که دارد، ما نیز در این مقاله از آن استفاده می کنیم.

یک نکته جالب توجه این است که تمام لینک ها ،  آدرس های (URL)کامل هستند.آدرس های مرتبط هم مجاز هستند اما شما باید یک ،تک آدرس پایه را مشخص کنید که به ابتدای همه ی آدرس ها اضافه شده باشد.

پیاده سازی Atom Feed:

به این صورت یک Feed جدید ایجاد می کنیم:

SyndicationFeed feed = new SyndicationFeed()
{
    // id (Required) - The feed universally unique identifier.
    Id = "3D797739-1DED-4DB8-B60B-1CA52D0AA1A4",
    // title (Required) - Contains a human readable title for the feed. Often the same as the title of the 
    //                    associated website. This value should not be blank.
    Title = SyndicationContent.CreatePlaintextContent("ASP.NET MVC Boilerplate"),
    // items (Required) - The entries to add to the feed. I'll cover how to do this further on.
    Items = this.GetItems(),
    // subtitle (Recommended) - Contains a human-readable description or subtitle for the feed.
    Description = SyndicationContent.CreatePlaintextContent(
        "This is the ASP.NET MVC Boilerplate feed description."),
    // updated (Optional) - Indicates the last time the feed was modified in a significant way.
    LastUpdatedTime = DateTimeOffset.Now,
    // logo (Optional) - Identifies a larger image which provides visual identification for the feed. 
    //                   Images should be twice as wide as they are tall.
    ImageUrl = new Uri("http://example.com/icons/atom-logo-96x48.png"),
    // rights (Optional) - Conveys information about rights, e.g. copyrights, held in and over the feed.
    Copyright = SyndicationContent.CreatePlaintextContent(
        string.Format("© {0} - {1}", DateTime.Now.Year, "Rehan Saeed")),
    // lang (Optional) - The language of the feed.
    Language = "en-GB",
    // generator (Optional) - Identifies the software used to generate the feed, for debugging and other 
    //                        purposes. Do not put in anything that identifies the technology you are using.
    // Generator = "Sample Code",
    // base (Buggy) - Add the full base URL to the site so that all other links can be relative. This is 
    //                great, except some feed readers are buggy with it, INCLUDING FIREFOX!!! 
    //                (See https://bugzilla.mozilla.org/show_bug.cgi?id=480600).
    // BaseUri = new Uri("http://example.com")
};
 
// self link (Required) - The URL for the syndication feed.
feed.Links.Add(SyndicationLink.CreateSelfLink(
    new Uri("http://example.com/feed/"), 
    ContentType.Atom));
 
// alternate link (Recommended) - The URL for the web page showing the same data as the syndication feed.
feed.Links.Add(SyndicationLink.CreateAlternateLink(
    new Uri("http://example.com"), 
    ContentType.Html));
 
// hub link (Recommended) - The URL for the PubSubHubbub hub. Used to push new entries to subscribers 
//                          instead of making them poll the feed. See feed updated method below.
feed.Links.Add(new SyndicationLink(new Uri("https://pubsubhubbub.appspot.com/"), "hub", null, null, 0));
 
// author (Recommended) - Names one author of the feed. A feed may have multiple author elements. A feed 
//                        must contain at least one author element unless all of the entry elements contain 
//                        at least one author element.
feed.Authors.Add(
    new SyndicationPerson()
    {
        // name (Required) - conveys a human-readable name for the person.
        Name = "Rehan Saeed",
        // uri (Optional) - contains a home page for the person.
        Uri = "http://rehansaeed.com",
        // email (Optional) - contains an email address for the person.
        Email = "example@email.com"
    });
 
// category (Optional) - Specifies a category that the feed belongs to. A feed may have multiple category 
//                       elements.
feed.Categories.Add(new SyndicationCategory("CategoryName"));
 
// contributor (Optional) - Names one contributor to the feed. An feed may have multiple contributor 
//                          elements.
feed.Contributors.Add(
    new SyndicationPerson()
    {
        Name = "Rehan Saeed",
        Uri = "http://rehansaeed.com",
        Email = "example@email.com"
    });
 
// icon (Optional) - Identifies a small image which provides iconic visual identification for the feed. 
//                   Icons should be square.
feed.SetIcon(this.urlHelper.AbsoluteContent("http://example.com/icons/atom-icon-48x48.png"));
 
// Add the Yahoo Media namespace (xmlns:media="http://search.yahoo.com/mrss/") to the Atom feed. 
// This gives us extra abilities, like the ability to give thumbnail images to entries. 
// See http://www.rssboard.org/media-rss for more information.
feed.AddYahooMediaNamespace();

متاسفانه ،property که icon   را تنظیم کند روی SyndicationFeed  موجود نمی باشد،  باوجود اینکه آن قسمتی از مشخصات رسمی  می باشد. خوشبختانه ما در اینجا یک متد افزونه که  به ما اجازه می دهد icon  را تنظیم کنیم داریم.

همچنین ما یک متد افزونه ی دیگر برای اضافه کردن media thumbnail یاهو به Atom entry  ایجاد کردیم. این یک افزونه غیراستاندارد می باشد اما ارزش تلاش داشت.برای استفاده از افزونه غیراستاندارد ، نیاز به اضافه کردن فضانام به المان Feed  در XML  می باشد، این کاری است که متد AddYahooMediaNamespace  به شکل زیر انجام می دهد.

متد های افزونه در زیر نشان داده شده است آنها از نقاط قابل توسعه روی SyndicationFeed استفاده می کنند.

/// <summary>
/// <see cref="SyndicationFeed"/> extension methods.
/// </summary>
public static class SyndicationFeedExtensions
{
    private const string YahooMediaNamespacePrefix = "media";
    private const string YahooMediaNamespace = "http://search.yahoo.com/mrss/";
 
    /// <summary>
    /// Adds a namespace to the specified feed.
    /// </summary>
    /// <param name="feed">The syndication feed.</param>
    /// <param name="namespacePrefix">The namespace prefix.</param>
    /// <param name="xmlNamespace">The XML namespace.</param>
    public static void AddNamespace(this SyndicationFeed feed, string namespacePrefix, string xmlNamespace)
    {
        feed.AttributeExtensions.Add(
            new XmlQualifiedName(namespacePrefix, XNamespace.Xmlns.ToString()), 
            xmlNamespace);
    }
 
    /// <summary>
    /// Adds the yahoo media namespace to the specified feed.
    /// </summary>
    /// <param name="feed">The syndication feed.</param>
    public static void AddYahooMediaNamespace(this SyndicationFeed feed)
    {
        AddNamespace(feed, YahooMediaNamespacePrefix, YahooMediaNamespace);
    }
 
    /// <summary>
    /// Gets the icon URL for the feed.
    /// </summary>
    /// <param name="feed">The syndication feed.</param>
    /// <returns>The icon URL.</returns>
    public static string GetIcon(this SyndicationFeed feed)
    {
        SyndicationElementExtension iconExtension = feed.ElementExtensions.FirstOrDefault(
            x => string.Equals(x.OuterName, "icon", StringComparison.OrdinalIgnoreCase));
        return iconExtension.GetObject<string>();
    }
 
    /// <summary>
    /// Sets the icon URL for the feed.
    /// </summary>
    /// <param name="feed">The syndication feed.</param>
    /// <param name="iconUrl">The icon URL.</param>
    public static void SetIcon(this SyndicationFeed feed, string iconUrl)
    {
        feed.ElementExtensions.Add(new SyndicationElementExtension("icon", null, iconUrl));
    }
 
    /// <summary>
    /// Sets the Yahoo Media thumbnail for the feed entry.
    /// </summary>
    /// <param name="item">The feed entry.</param>
    /// <param name="url">The thumbnail URL.</param>
    /// <param name="width">The optional width of the thumbnail image.</param>
    /// <param name="height">The optional height of the thumbnail image.</param>
    public static void SetThumbnail(this SyndicationItem item, string url, int? width, int? height)
    {
        XNamespace ns = YahooMediaNamespace;
        item.ElementExtensions.Add(new SyndicationElementExtension(
            new XElement(
                ns + "thumbnail",
                new XAttribute("url", url),
                width.HasValue ? new XAttribute("width", width) : null,
                height.HasValue ? new XAttribute("height", height) : null)));
    }

 

یک مثال از ایجاد اولین entry  در زیر نشان داده ایم.

SyndicationItem item = new SyndicationItem()
{
    // id (Required) - Identifies the entry using a universally unique and permanent URI. Two entries 
    //                 in a feed can have the same value for id if they represent the same entry at 
    //                 different points in time.
    Id = "6139F098-2E59-4405-9BC7-0AAB4CF78E23",
    // title (Required) - Contains a human readable title for the entry. This value should not be blank.
    Title = SyndicationContent.CreatePlaintextContent("Item 1"),
    // description (Recommended) - A summary of the entry.
    Summary = SyndicationContent.CreatePlaintextContent("A summary of item 1"),
    // updated (Optional) - Indicates the last time the entry was modified in a significant way. This 
    //                      value need not change after a typo is fixed, only after a substantial 
    //                      modification. Generally, different entries in a feed will have different 
    //                      updated timestamps.
    LastUpdatedTime = DateTimeOffset.Now,
    // published (Optional) - Contains the time of the initial creation or first availability of the entry.
    PublishDate = DateTimeOffset.Now,
    // rights (Optional) - Conveys information about rights, e.g. copyrights, held in and over the entry.
    Copyright = new TextSyndicationContent(
        string.Format("© {0} - {1}", DateTime.Now.Year, "Rehan Saeed")),
};
 
// link (Recommended) - Identifies a related Web page. An entry must contain an alternate link if there 
//                      is no content element.
item.Links.Add(SyndicationLink.CreateAlternateLink(
    new Uri("http://example.com/item1"), 
    ContentType.Html));
// AND/OR
// Text content  (Optional) - Contains or links to the complete content of the entry. Content must be 
//                            provided if there is no alternate link.
// item.Content = SyndicationContent.CreatePlaintextContent("The actual plain text content of the entry");
// HTML content (Optional) - Content can be plain text or HTML. Here is a HTML example.
// item.Content = SyndicationContent.CreateHtmlContent("The actual HTML content of the entry");
 
// author (Optional) - Names one author of the entry. An entry may have multiple authors. An entry must 
//                     contain at least one author element unless there is an author element in the 
//                     enclosing feed, or there is an author element in the enclosed source element.
item.Authors.Add(this.GetPerson());
 
// contributor (Optional) - Names one contributor to the entry. An entry may have multiple contributor elements.
item.Contributors.Add(this.GetPerson());
 
// category (Optional) - Specifies a category that the entry belongs to. A entry may have multiple 
//                       category elements.
item.Categories.Add(new SyndicationCategory("Category 1"));
 
// link - Add additional links to related images, audio or video like so.
item.Links.Add(SyndicationLink.CreateMediaEnclosureLink(
    new Uri("http://example.com/item1/atom-icon-48x48.png"), 
    ContentType.Png, 
    0));
 
// media:thumbnail - Add a Yahoo Media thumbnail for the entry. See http://www.rssboard.org/media-rss 
//                   for more information.
item.SetThumbnail("http://example.com/item1/atom-icon-48x48.png", 48, 48);
 
items.Add(item);

حال ممکن است که  داخل feed entry یک صفحه کامل از HTML  باشد. متناوبا ،شما می توانید مطالب متن ساده یا  همانطوری که ما انجام دادیم ، یک لینک به متن کامل ارائه کنیم.ما به شما نشان می دهیم که چگونه  سه مطلب بالا را انجام دهید.

قدم بعدی در واقع  پاسخگویی به  کاربر با پاسخ های HTTP  که شامل Atom 1.0 XML است،می باشد. همچنین Atom  فقط XML می باشد.که طرح های خاص خود را دارد و دارای نوع  MIME  مخصوص به خود به صورت ‘application/atom+xml’  می باشد. علاوه براین، XML باید درواقع با استفاده از رمزگذاری  کاراکتر UTF-8 طبق استاندارد بازگردانده شود.بنابراین در اینجا controllers action  ما feed  را برمی گرداند.

[OutputCache(Duration = 86400)]
[Route("feed", Name = "GetFeed")]
public ActionResult Feed()
{
    SyndicationFeed feed = this.feedService.GetFeed();
    return new AtomActionResult(feed);
}

Control Actionبالا ،فوق العاده ساده می باشد،  ما SyndicationFeed خود را می گیریم ودر  AtomActionResult جدید بازمیگردانیم.که این جا جاییست که همه  سحر و جادو رخ می دهد.ما همچنین پاسخ( response) را برای یک روز ذخیره می کنیم ، که اینکار کارایی (performance ) بسیار خوبی دارد ،اگر شما Feed خود را زیاد تغییر ندهید.

 بنابراین  AtomActionResult  چیست ،که در اینجا به خوبی در کد آمده است.

/// <summary>
/// Represents a class that is used to render an Atom 1.0 feed by using an <see cref="SyndicationFeed"/> instance 
/// representing the feed.
/// </summary>
public sealed class AtomActionResult : ActionResult
{
    private readonly SyndicationFeed syndicationFeed;
 
    /// <summary>
    /// Initializes a new instance of the <see cref="AtomActionResult"/> class.
    /// </summary>
    /// <param name="syndicationFeed">The Atom 1.0 <see cref="SyndicationFeed" />.</param>
    public AtomActionResult(SyndicationFeed syndicationFeed)
    {
        this.syndicationFeed = syndicationFeed;
    }
 
    /// <summary>
    /// Executes the call to the ActionResult method and returns the created feed to the output response.
    /// </summary>
    /// <param name="context">The context in which the result is executed. The context information includes the 
    /// controller, HTTP content, request context, and route data.</param>
    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.ContentType = "application/atom+xml";
        Atom10FeedFormatter feedFormatter = new Atom10FeedFormatter(this.syndicationFeed);
        XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
        xmlWriterSettings.Encoding = Encoding.UTF8;
 
        if (HttpContext.Current.IsDebuggingEnabled)
        {
            // Indent the XML for easier viewing but only in Debug mode. In Release mode, everything is output on 
            // one line for best performance.
            xmlWriterSettings.Indent = true;
        }
 
        using (XmlWriter xmlWriter = XmlWriter.Create(context.HttpContext.Response.Output, xmlWriterSettings))
        {
            feedFormatter.WriteTo(xmlWriter);
        }
    }
}

کد بالا در خارج از XML  برای پاسخ HTTP  در رمزگداری UTF-8 و به همراه  ‘application/atom+xml’ از نوع MIME نوشته شده است.به صورت پیش فرض XML  همه در یک خط  نوشته می شود که از لحاظ performance بسیار خوب است اما از لحاظ خوانایی مناسب نمی باشد.بنابراین ما همچنین تشخیص می دهیم که آیا برنامه دیباگ شده است اگر چنین است تمام تورفتگی ها را رعایت می کنیم برای خوانایی بهتر.

بعد از همه کار سخت ما ،حال می توانیم  controller action را هدایت کنیم و Feed خود را مشاهده کنیم.

در این جا یک نمایی از Atom feed ما درInternet Explorer’s می باشد.

عکس ها:

RSS  وAtom   حدودا بیش از یک دهه است که کار خود را آغاز کرده اند و حالا اطلاعات باارزش بسیار کمی  در مورد چگونگی ایجاد Feed وجود دارد. یکی از بخش های فاقد اطلاعات، عکس های لوگو و آیکون می باشد. همه این مشخصات می گوید نسبت عکس ها باید به ترتیب ، مستطیل 2:1 و مربع 1:1 باشند.

پیشنهاد ما به شما این است که به دنبال نمونه های مختلف از Feed  در اینترنت بروید و سایز عکس هایی که آنجا استفاده شده را کپی کنید. ما با  تصاویری به اندازه 48×48 و 96×48 که معمولا سایز رایجی می باشد کار را به پایان می رسانیم.

اضافه کردن دکمه ‘Subscribe to this page’ :

فایرفاکس یک ویژگی دارد به اسم ‘Subscribe to this page’ که یک دکمه می باشد که کاربران می توانند به toolbar خود اضافه کنند(در ورژن قدیمی فایرفاکس ، این دکمه به طور پیش فرض فعال است ) این دکمه تشخیص می دهد که آیا صفحه ی فعلی  به  RSS/Atom feed لینک  می باشد اگربود کاربر می تواند بر روی آن کلیک کند تا مستقیما Feed را تصدیق کند . در این جا یک تصویر از دکمه می باشد.

 برای اضافه کردن این ویژگی ،ما نیاز داریم که meta tag  را در بالای صفحه قرار دهیم با  لینک به Atom feed مانند زیر:

	<link href="http://localhost/feed" rel="alternate" title="ASP.NET MVC Boilerplate Feed" type="application/atom+xml">

این یکی از ویژگی های بسیار جزئی ، اما دارای پتانسیل است. با انجام این کار ، صفحه ی ما به Atom feed لینک می شود . همچنین می تواند از طریق موتور جستجو خوانده شود. بنابراین به طور بالقوه ،یک  مزایا از نظر بهینه سازی موتور جستجو (SEO)  می تواند  به حساب بیاید. البته این، غیر ممکن است که به نحوه ی رتبه بندی موتور جستجو پی ببریم.

PubSubHubbub :

از مشکلات Feed ها این است که  شما باید، اطلاعات را از آنها استخراج کنید.شما هیچ گاه از تغییرات جدید مطلع نمی شوید ،بنابراین مشتریان باید به طور مداوم به feed  رجوع کنند برای چک کردن  هر Feed جدیدی که وارد شده است.

مشکل PubSubHubbub حل شد . PubSubHubbub توسط گوگل توسعه یافت و درواقع آخرین نسخه  standardآن نسخه 0.4 می باشد.

درحال حاضر عمده ای از سیستم عامل ها از آخرین نسخه standard حمایت میکنند. با وجود آن که ازمحصولات گوگل  ، بیشترانتظار می رود که از آن ها پشتیبانی کند اما وردپرس هم به عنوان  قدرت سوم در دنیای وب سایت، از آخرین نسخه standard پشتیبانی می کند.

در قالب این نسخه ، یک hub  وجود دارد که می داند که چگونه به زبان استاندارد PubSubHubbub صحبت کند.وقتی که یک Feed  با یک entry  جدید ، به روز رسانی شده است . کاربران می توانند برای به روز رسانی با hub    وبرای آن که  بلافاصله هنگامی که به روزرسانی انجام شد ،مطلع شوند، ثبت نام  کنند.

نکته جالب این است که همه ی این ها بسیار ساده برای پیاده سازی می باشند،از زمانی که گوگلhub   را ارائه داد ما  می توانیم از این قابلیت استفاده کنیم ودیگرنیازی به نوشتن ما  نمی باشد.ما فقط نیاز داریم یک خط از XML  در Atom feed خود اضافه کنیم که به کاربر بگوییم که از PubSubHubbub و URL که برای Hub  می خواهیم استفاده کنیم ، پشتیبانی می کنیم.

<link rel="hub" href="https://pubsubhubbub.appspot.com/" />

زمانی که Feed  ما به روز رسانی شد ، این به روزرسانی را به لینک hub  بالا منتشر می کنیم .ما این کار را با صدا زدن متد ساده زیر انجام می دهیم:

/// <summary>
/// Publishes the fact that the feed has updated to subscribers using the PubSubHubbub v0.4 protocol.
/// </summary>
public Task PublishUpdate()
{
    HttpClient httpClient = new HttpClient();
    return httpClient.PostAsync(
        "https://pubsubhubbub.appspot.com/", 
        new FormUrlEncodedContent(
            new KeyValuePair<string, string>[]
            {
                new KeyValuePair<string, string>("hub.mode", "publish"),
                new KeyValuePair<string, string>(
                    "hub.url", 
                    "http://localhost/feed")
            }));
}

در سمت منتشر کنندگان(Publisher)   این کار به آسانی انجام می شود .درسمت کاربر (Client)به اشتراک گذاشتن تغییرات روی Feed یک مقدار پیچیده تر می باشد.

Feed Paging:

مشخصات Atom  درواقع به شما شرح می دهد که چگونه صفحه بندی(Paging) را به Feed خود اضافه کنید. این یک راه بسیار خوب برای تقسیم کردن feed  شما می باشد ، اگر نگران مصرف  بیش از حد پهنای باند خود هستید.اضافه کردن صفحه بندی(Paging)  ، شامل قراردادن لینک های زیر به بالای Feed  شما.  لینک ها، صفحات اول ، آخر ،بعدی و قبلی از Feed شما می باشند. واضح است ، اگر شما صفحه بعد و قبل را نداشته باشید ، آن لینک ها می توانند حذف شوند.

	  <link rel="first" href="http://example.com/feed"/>
    <link rel="next" href="http://example.com/feed?page=4"/>
<link rel="previous" href="http://example.com/feed?page=2"/> 
   <link rel="last" href="http://example.com/feed?page=10"/>

 کد متناظر، برای اضافه کردن لینک بالا می باشد:

feed.Links.Add(new SyndicationLink(new Uri("http://example.com/feed"), "first", null, null, 0));
feed.Links.Add(new SyndicationLink(new Uri("http://example.com/feed?page=10"), "last", null, null, 0));
 
if ([HAS_PREVIOUS_PAGE])
{
    feed.Links.Add(new SyndicationLink(new Uri("http://example.com/feed?page=2")), "previous", null, null, 0));
}
 
if ([HAS_NEXT_PAGE])
{
    feed.Links.Add(new SyndicationLink(new Uri("http://example.com/feed?page=4"), "next", null, null, 0));
}

اعتبار سنجی Feed :

یکبار  Feed  خود را Build  کنید و آن را به صورت آنلاین منتشر (Publish)  کنید، فراموش نکنید که با FeedValidator.org چک کنید تا مطمئن شوید که با Atom 1.0 ، مطابقت دارد یا خیر.

آموزش سی شارپ

آموزش asp.net mvc

فایل های ضمیمه