RSS ke 66 jejaring sosial: Facebook, Instagram, X, LinkedIn, Telegram, dan lainnya Blog Afiliasi Kontak
Masuk Mulai gratis
Updated: 2026-10-06
ASP.NET Core RSS Feed with SyndicationFeed: Build and Auto-Post

Short answer: An ASP.NET Core RSS feed is one endpoint. Add the System.ServiceModel.Syndication package, build a SyndicationFeed from your latest published posts with absolute URLs and UTC dates, write it with Rss20FeedFormatter through an XmlWriter set to UTF-8, and return it as application/rss+xml with output caching. Validate it once and any RSS auto-poster can share every new article automatically.

ASP.NET Core runs company websites, intranets, documentation portals, SaaS marketing sites and blogs built on custom .NET back ends. Unlike a packaged CMS, it does not give you a feed out of the box, so many .NET sites simply never publish one. That is a missed opportunity: a feed is what lets readers subscribe, newsletters pull your latest content and social automation tools share each article the moment it goes live. This guide shows a reliable way to build the feed with minimal APIs or MVC, the mistakes that most often break .NET feeds, and how to connect the result to social auto-posting.

What an ASP.NET Core RSS feed must provide

Agree on the target before you write code. A dependable feed:

  • lists your most recent public items, newest first, typically 20 to 50;
  • gives each item a title, an absolute link, a summary, a publication date and a permanent unique ID;
  • describes the channel with a title, a link to the site and a short description;
  • is served as RSS or XML, encoded and declared as UTF-8, with no redirects;
  • stays stable, so tools never treat an old item as new.

Images and categories are optional, but they matter a lot when the feed drives social posts, so we will add them once the basic version works.

Step 1: add the syndication package

.NET includes a mature feed model in the System.ServiceModel.Syndication namespace. In modern .NET it ships as a NuGet package:

dotnet add package System.ServiceModel.Syndication

The package gives you SyndicationFeed dan SyndicationItem classes plus formatters for RSS 2.0 and Atom 1.0. Because the formatter writes the XML, escaping of titles and summaries is handled for you, which removes the most common source of broken hand-made feeds. The SyndicationFeed API reference lists every property if you need more than the basics shown here.

Step 2: build the feed in a minimal API endpoint

The example assumes an Entity Framework Core context BlogDb with a Posts set whose entities have Title, Slug, Summary, PublishedAt (stored in UTC) and IsPublished. The public base address comes from configuration, which is the most predictable way to get correct absolute links.

using System.ServiceModel.Syndication;
using System.Text;
using System.Xml;
using Microsoft.EntityFrameworkCore;

app.MapGet("/rss.xml", async (BlogDb db, IConfiguration config) =>
{
    var baseUrl = config["Site:BaseUrl"]!.TrimEnd('/');
    var now = DateTime.UtcNow;

    var posts = await db.Posts
        .Where(p => p.IsPublished && p.PublishedAt <= now)
        .OrderByDescending(p => p.PublishedAt)
        .Take(30)
        .ToListAsync();

    var items = posts.Select(p =>
    {
        var url = $"{baseUrl}/blog/{p.Slug}";
        var item = new SyndicationItem(p.Title, p.Summary, new Uri(url), url,
            new DateTimeOffset(DateTime.SpecifyKind(p.PublishedAt, DateTimeKind.Utc)));
        item.PublishDate = item.LastUpdatedTime;
        return item;
    }).ToList();

    var feed = new SyndicationFeed("Example Blog", "New articles from Example",
        new Uri(baseUrl + "/"), items)
    {
        Language = "en"
    };

    var settings = new XmlWriterSettings
    {
        Encoding = new UTF8Encoding(false),
        Indent = true
    };
    using var stream = new MemoryStream();
    using (var writer = XmlWriter.Create(stream, settings))
    {
        new Rss20FeedFormatter(feed, false).WriteTo(writer);
    }

    return Results.File(stream.ToArray(), "application/rss+xml; charset=utf-8");
})
.CacheOutput(p => p.Expire(TimeSpan.FromMinutes(5)));

A few lines deserve attention. The query filters on both the published flag and the publication date, so drafts and scheduled posts stay out of the feed. The item ID is the permanent article URL, which becomes the item’s guid and should never change. The PublishDate is set explicitly, because RSS readers and auto-posting tools rely on pubDate. And the writer writes into a byte stream with UTF-8 encoding, which avoids the encoding trap described next.

The UTF-16 trap and other encoding issues

The most famous .NET feed bug is a feed that declares encoding="utf-16". It happens when the formatter writes to a StringWriter: .NET strings are UTF-16 internally, so the writer announces UTF-16 in the XML declaration, while the HTTP response is actually sent as UTF-8. Some readers cope; many validators and auto-posting tools reject the feed or show broken characters.

  • Write to a stream, not a string. Use a MemoryStream or the response body with XmlWriterSettings.Encoding set to UTF-8, as in the example.
  • Avoid the byte order mark. new UTF8Encoding(false) writes UTF-8 without a BOM. A BOM before the XML declaration confuses some parsers.
  • Keep the declaration and the header consistent. The XML says UTF-8, and the content type says charset=utf-8.

If characters such as quotes, accents or emoji still look wrong in social posts, our guide to encoding issues in RSS feeds walks through the usual causes.

The MVC controller alternative

If your project uses controllers instead of minimal APIs, the feed code moves into an action almost unchanged. Put the feed-building logic into a small service, for example IFeedBuilder, register it in dependency injection, and call it from a controller action decorated with [HttpGet("rss.xml")]. Return File(bytes, "application/rss+xml; charset=utf-8") from the action.

A shared service has another advantage: the main feed, category feeds and your tests all use one implementation. When you later add images or categories to items, every feed gets them at once, and nothing drifts apart.

Absolute URLs behind a proxy

The example takes the base address from configuration, which is the safest option. If you prefer to build URLs from the request, for instance with LinkGenerator.GetUriByName, remember that behind Nginx, IIS, a load balancer or a container platform the app may see an internal scheme and host.

  • Use the forwarded headers middleware. Call app.UseForwardedHeaders() early in the pipeline with ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto, and add the proxy to KnownProxies atau KnownNetworks when it is not on the same machine.
  • Check the live output. Open the feed on the public domain and search for http://, localhost and internal host names. None should appear.
  • Never output relative links. They work in Razor pages but break once an item is read elsewhere. Our article on relative URLs and broken links in RSS feeds explains why.

Images, categories and discovery

Richer items produce better social posts. After the basic feed validates, consider:

  • An image per item. Add a link with relationship type enclosure: item.Links.Add(SyndicationLink.CreateMediaEnclosureLink(new Uri(imageUrl), "image/jpeg", length)). Use an absolute URL to a reasonably sized image; many auto-posting tools use it as the post picture.
  • Categories. item.Categories.Add(new SyndicationCategory("Tutorials")) writes a category element that tools can turn into hashtags or use for filtering.
  • Open Graph tags. Make sure every article page has og:title, og:description dan og:image, because tools often fall back to them.
  • Autodiscovery. In _Layout.cshtml, add <link rel="alternate" type="application/rss+xml" title="Example Blog" href="https://example.com/rss.xml"> so browsers and tools can find the feed from any page.

Category feeds

One site-wide feed is enough to begin. Later, per-category feeds help readers who want a single topic and make it simple to send different subjects to different social channels. In a minimal API, map a second route such as /category/{slug}/rss.xml, look up the category, return Results.NotFound() when it does not exist, and pass the filtered posts to the same feed builder with a category-specific title.

Keep the GUID of each article identical in every feed that contains it. Tools that follow both the main feed and a category feed will then recognise the article as one item and will not post it twice. If you ever do see duplicates, the guide on duplicate GUID fixes explains how auto-posters decide what is new.

Caching and conditional requests

Feeds are polled constantly. Readers, aggregators and auto-posting services request them on a schedule, often every few minutes. Without caching, every request runs a database query and builds XML.

  • Output caching. In .NET 7 and later, register it with builder.Services.AddOutputCache(), enable it with app.UseOutputCache() and attach a short policy to the endpoint, as in the example. Five minutes is a good default.
  • Evict on publish. If posts must appear immediately, tag the cached entry and evict that tag from the code that publishes an article.
  • Last-Modified and ETag. Setting these headers lets well-behaved clients ask whether anything changed and receive a short 304 response instead of the full document.
  • Keep the payload small. Thirty items with summaries is plenty for subscribers and automation.

Long cache lifetimes delay auto-posting, so keep them short. Our explanation of how feed caching makes auto-posts lag shows the effect in practice.

Test and troubleshoot

An integration test with WebApplicationFactory protects the feed from regressions. Request /rss.xml with the test client, assert status 200 and the RSS content type, load the body with XDocument.Parse and check that the first item has a title, an absolute link and a pubDate. Also assert that the declaration does not mention UTF-16.

ProblemTypical cause in ASP.NET CoreFix
Feed declares utf-16Formatter writes to a StringWriterWrite to a stream with UTF-8 XmlWriterSettings
Links use http or an internal hostForwarded headers not processedUse a configured base URL or UseForwardedHeaders
Dates shifted by hoursDateTime with Unspecified kindStore UTC and use SpecifyKind before conversion
Scheduled posts visible earlyQuery ignores PublishedAtFilter on PublishedAt <= DateTime.UtcNow
Same post shared twiceItem ID built from an editable titleUse the permanent URL or database ID
Feed downloads as a fileGeneric content typeReturn application/rss+xml; charset=utf-8

Before connecting automation, fetch the headers with curl -I, expect HTTP 200 without redirects, run the URL through the W3C Feed Validation Service and open a few item links in a private window to confirm they are public.

Connect the feed to social auto-posting

Once the feed is valid, sharing no longer depends on someone remembering to post. Add the feed URL to an auto-posting service, connect your social accounts and channels, decide how posts are built from the title, summary and link, and choose posting hours if you need them. The service checks the feed and publishes each new item once.

.NET teams often route content by audience: company news to a professional network, engineering posts to Mastodon or Bluesky, release notes to a Telegram channel, Discord server or team chat. Category feeds make each route a simple matter of choosing the right feed. More examples are collected under technical guides and the Feed RSS topic.

How PostRSS works with an ASP.NET Core feed

PostRSS reads any RSS or Atom feed, including one produced by Rss20FeedFormatter, and publishes each new item to the networks you connect. It checks feeds as often as every minute, uses the image from the feed item or the page’s Open Graph tags, and offers keyword filters, hashtags from item categories and UTM parameters. Developers can also use the PostRSS REST API v1 and outgoing webhooks, and the service has been running since 2014. See the features page for all 66 networks and the pricing page for what each plan includes.

Related reading

The bottom line

An ASP.NET Core RSS feed needs one endpoint and a few careful choices: the syndication package for safe XML, a configured HTTPS base URL, UTC dates, permanent item IDs, UTF-8 output written to a stream, the right content type and a short output cache. Add images and categories, put a discovery link in the layout, cover the endpoint with an integration test and validate it once. After that the feed keeps working quietly, and every new article reaches subscribers and your social channels without anyone sharing it by hand.

FAQ

Does ASP.NET Core include RSS support?

Not in the core framework, but the System.ServiceModel.Syndication NuGet package provides feed classes and RSS 2.0 and Atom formatters that work in any ASP.NET Core project.

Why does my .NET feed say encoding utf-16?

The formatter was written to a StringWriter, which declares UTF-16. Write to a stream with XmlWriterSettings set to UTF-8 so the declaration matches the response.

Should I use minimal APIs or an MVC controller?

Either works. Minimal APIs keep a feed endpoint very short, while a controller fits projects that already use MVC. Put the feed logic in a shared service in both cases.

How long should I cache the feed?

A few minutes is a good balance. It removes most of the load from frequent polling while new articles still reach readers and auto-posting tools quickly.

Can I auto-post new ASP.NET Core articles to social media?

Yes. Once the feed is public and valid, an RSS auto-posting service can watch it and publish each new article to the social networks and channels you connect.

New guides, once a month

What changed in the networks, what broke, and how to fix it before it costs you reach.

We send a confirmation e-mail first. Unsubscribe any time.

Alat lain dari tim kami

Dibuat oleh Internet Solutions, tim di balik PostRSS. Masing-masing menghemat waktu Anda dengan caranya sendiri.

PostRSS - Platform Otomatisasi RSS Feed & Alat Auto-Posting
Ikhtisar Privasi

Situs web ini menggunakan cookie agar kami dapat memberikan pengalaman pengguna terbaik bagi Anda. Informasi cookie disimpan di browser Anda dan menjalankan fungsi seperti mengenali Anda saat Anda kembali ke situs web kami serta membantu tim kami memahami bagian situs web mana yang menurut Anda paling menarik dan bermanfaat.