Back to "Ajout d'un flux RSS avec 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

Ajout d'un flux RSS avec ASP.NET Core

Wednesday, 07 August 2024

Présentation

RSS (et Atom) est toujours le seul format largement adopté pour syndiquer le contenu. C'est un format XML simple qui peut être consommé par un large éventail de lecteurs de flux. Dans ce billet, je vais vous montrer comment ajouter un flux RSS à votre application ASP.NET Core.

Création de l'alimentation

Vraiment le cœur de cela est de créer le document XML pour le flux RSS. Le code ci-dessous prend une liste de RssFeedItem objets et génère le XML pour le flux. Les RssFeedItem classe est une classe simple qui représente un élément dans l'alimentation. Il possède des propriétés pour le titre, le lien, la description, la date de publication et les catégories.

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

Points à noter dans le code ci-dessus: Nous devons créer l'espace de noms Atom et l'injecter dans le document XML pour prendre en charge le atom:link élément.

     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"),

Encodage UTF-8

Bien que nous spécifions utf-8 ASP.NET Core ignore ça... parce que c'est spécial. Au lieu de cela, nous devons nous assurer que les chaînes générées dans le document sont en fait UTF-8, j'avais pensé que

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

Mais NOPE... nous devons le faire :

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

De cette façon, il produit en fait un document XML avec un encodage utf-8.

Le contrôleur

De là, c'est assez simple dans le RSSController, nous avons une méthode qui accepte category et startdate (actuellement une caractéristique super secrète??) et retourne le flux.

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

ENSEMBLE dans le '_Layout.cshtml' nous ajoutons un lien vers le flux:

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

Cela garantit que le flux peut être 'autodécouvert' par les lecteurs de flux.

logo

©2024 Scott Galloway