Back to "Προσθήκη μιας RSS feed με ASP.NET Core"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

ASP.NET RSS

Προσθήκη μιας RSS feed με ASP.NET Core

Wednesday, 07 August 2024

Εισαγωγή

RSS (και Atom) εξακολουθεί να είναι η μόνη ευρέως υιοθετημένη μορφή για τη σύνθεση του περιεχομένου. Είναι μια απλή μορφή XML που μπορεί να καταναλωθεί από ένα ευρύ φάσμα αναγνωστών ζωοτροφών. Σε αυτή τη δημοσίευση, θα σας δείξω πώς να προσθέσετε μια RSS feed στην εφαρμογή σας ASP.NET Core.

Δημιουργία της τροφής

Πραγματικά ο πυρήνας αυτού είναι η δημιουργία του εγγράφου XML για την τροφοδοσία RSS. Ο παρακάτω κώδικας λαμβάνει μια λίστα των RssFeedItem αντικείμενα και παράγει το XML για την τροφή. Η RssFeedItem κατηγορία είναι μια απλή κατηγορία που αντιπροσωπεύει ένα στοιχείο στην τροφή. Έχει ιδιότητες για τον τίτλο, το σύνδεσμο, την περιγραφή, την ημερομηνία δημοσίευσης και τις κατηγορίες.

    public string GenerateFeed(IEnumerable<RssFeedItem> items, string categoryName = "")
    {
        XNamespace atom = "http://www.w3.org/2005/Atom";
        var feed = new XDocument(
            new XDeclaration("1.0", "utf-8", null),
            new XElement("rss",    new XAttribute(XNamespace.Xmlns + "atom", atom.NamespaceName), new XAttribute("version", "2.0"),
                new XElement("channel",
                    new XElement("title", !string.IsNullOrEmpty(categoryName) ? $"mostlylucid.net for {categoryName}" : $"mostlylucid.net"),
                    new XElement("link", $"{GetSiteUrl()}/rss"),
                    new XElement("description", "The latest posts from mostlylucid.net"),
                    new XElement("pubDate", DateTime.UtcNow.ToString("R")),
                    new XElement(atom + "link", 
                        new XAttribute("href", $"{GetSiteUrl()}/rss"), 
                        new XAttribute("rel", "self"), 
                        new XAttribute("type", "application/rss+xml")),
                    from item in items
                    select new XElement("item",
                        new XElement("title", item.Title),
                        new XElement("link", item.Link),
                        new XElement("guid", item.Guid, new XAttribute("isPermaLink", "false")),
                        new XElement("description", item.Description),
                        new XElement("pubDate", item.PubDate.ToString("R")),
                        from category in item.Categories
                        select new XElement("category", category)
                    )
                )
            )
        );

        var settings = new XmlWriterSettings
        {
            Indent = true,
            Encoding = new UTF8Encoding(false) // UTF-8 without BOM
        };

        using (var memoryStream = new MemoryStream())
        using (var writer = XmlWriter.Create(memoryStream, settings))
        {
            feed.Save(writer);
            writer.Flush();
            return Encoding.UTF8.GetString(memoryStream.ToArray());
        }
    }

Σημειωματάρια στον παραπάνω κωδικό: Πρέπει να δημιουργήσουμε τον χώρο ονομάτων ατόμων και να τον εντάξουμε στο έγγραφο XML για να υποστηρίξουμε το atom:link στοιχείο.

     XNamespace atom = "http://www.w3.org/2005/Atom";
        var feed = new XDocument(
            new XDeclaration("1.0", "utf-8", null),
            new XElement("rss",    new XAttribute(XNamespace.Xmlns + "atom", atom.NamespaceName), new XAttribute("version", "2.0"),

Κωδικοποίηση UTF-8

Αν και θα καθορίσουμε... utf-8 Το ASP.NET Core το αγνοεί αυτό... γιατί είναι ξεχωριστό. Αντίθετα, πρέπει να διασφαλίσουμε ότι οι χορδές που παράγονται στο έγγραφο είναι στην πραγματικότητα UTF-8, είχα σκεφτεί αυτό

   var settings = new XmlWriterSettings
        {
            Indent = true,
            Encoding = new UTF8Encoding(false) // UTF-8 without BOM
        };

Αλλά NOPE... πρέπει να το κάνουμε αυτό:

        using (var memoryStream = new MemoryStream())
        using (var writer = XmlWriter.Create(memoryStream, settings))
        {
            feed.Save(writer);
            writer.Flush();
            return Encoding.UTF8.GetString(memoryStream.ToArray());
        }

Με αυτόν τον τρόπο παράγει ουσιαστικά ένα έγγραφο XML με κωδικοποίηση utf-8.

Ο ελεγκτής

Από εκεί είναι αρκετά απλό στο RSSController, έχουμε μια μέθοδο που δέχεται category και startdate (προς το παρόν ένα σούπερ μυστικό χαρακτηριστικό??) και επιστρέφει την τροφή.

    [HttpGet]
    public IActionResult Index([FromQuery] string category = null, [FromQuery] string startDate = null)
    {
        DateTime? startDateTime = null;
        if (DateTime.TryParseExact(startDate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None,
                out DateTime startDateTIme))
        {
            logger.LogInformation("Start date is {startDate}", startDate);
        }

        var rssFeed = rssFeedService.GenerateFeed(startDateTime, category);
        return Content(rssFeed, "application/rss+xml", Encoding.UTF8);
    }

ΤΟΤΕ, μέσα στο ~_Διάταξη.cshtml" προσθέτουμε ένα σύνδεσμο με την τροφή:

        <link rel="alternate" type="application/rss+xml"
              title="RSS Feed for mostlylucid.net"
              href="/rss" />

Αυτό εξασφαλίζει ότι η τροφή μπορεί να "ανακαλυφθεί" από τους αναγνώστες ζωοτροφών.

logo

©2024 Scott Galloway