Webalkalmazások fejlesztésekor gyakran merül fel az igény, hogy a tartalmat RSS formában is publikálnunk kell. Erre számtalan megoldás létezik, a .NET Framework 3.5 megjelenése óta azonban közvetlen támogatást ad a keretrendszer a System.ServiceModel.Syndication névtér osztályainak segítségével.
A névtér nevéből látszik, hogy a WCF részeként kapjuk ezt a szolgáltatást és a weben számtalan példát látunk arra, hogy akár egy konzol alkalmazásban hogyan hozhatunk létre egy WCF alapú szolgáltatást, amely RSS formában válaszol, arra azonban alig van utalás, hogy ez a funkció közvetlenül használható egy ASP.NET-es webalkalmazásban is.
A nem-HTML jellegű válasz előállításához szerintem leginkább IHttpHandlert érdemes használni:
Az IHttpHandler legfontosabb metódusa a ProcessRequest, amelyben közvetlenül a HttpContextbe kell beleírnunk a HTTP választ. Ha RSS 2.0 formában akarjuk visszaküldeni a választ és szeretnénk az elejére XML fejlécet, akkor azt megtehetjük például így:
public void ProcessRequest( HttpContext context )
{
// XML válasz típus beállítása.
context.Response.ContentType = "application/xml";
// XML fejléc beírása a válasz elejére.
XmlTextWriter writer = new XmlTextWriter( context.Response.Output );
writer.Formatting = Formatting.Indented;
writer.WriteProcessingInstruction( "xml", @"version=""1.0"" encoding=""utf-8""" );
// SyndicationFeed sorosítása RSS 2.0 formátumban.
this.BuildFeed().SaveAsRss20( writer );
}
Itt felhasználtam egy általam írt BuildFeed nevű segédmetódust, amely visszaadja az adatbázisban tárolt információk alapján összeállított SyndicationFeed objektumot.
A feed összeállítása az alap attribútumok beállításával kezdődik:
SyndicationFeed feed = new SyndicationFeed
{
Title = SyndicationContent.CreatePlaintextContent( "MSDN Kompetencia Központ" ),
Description = SyndicationContent.CreatePlaintextContent( "MSDN Kompetencia Központ RSS feedje" ),
Copyright = SyndicationContent.CreatePlaintextContent( "Copyright (C) MSDN Kompetencia Központ" ),
Language = "hu-HU",
ImageUrl = new Uri( imageUrl ),
Generator = "Cube"
};
Az egyes elemeket a feed objektum Items gyűjteményébe kell felvennünk SyndicationItemek formájában. Az elemek összerakása az új C# szintaktikával szintén aránylag tömören megoldható:
SyndicationItem item = new SyndicationItem
{
Title = SyndicationContent.CreatePlaintextContent( title ),
Content = SyndicationContent.CreateHtmlContent( body ),
PublishDate = date.ToUniversalTime(),
Id = articleUrl
};
Az itt felsoroltakon kívül még természetesen számos tulajdonságot tudunk megadni, melyek közül egyik-másik gyűjtemény, ilyen például a <link> tag:
item.Links.Add( SyndicationLink.CreateAlternateLink( new Uri( articleUrl ) ) );
Az RSS egyik érdekessége, hogy a séma bővíthető, akár más névtérbe tartozó XML elemekkel. A .NET-es objektum modell erre is ad támogatást az ElementExtensions és AttributeExtensions tulajdonságokon keresztül. Például ha szeretnénk felvenni egy <comments> tag-et a generált XML-be, amely egy URL címre mutat, akkor arra nem találunk saját tulajdonságot, de így mégis megtehetjük:
item.ElementExtensions.Add( "comments", null, commentsUrl );
Ha azonban azt is szeretnénk tárolni, hogy egy adott cikkhez hány hozzászólás tartozik, akkor egy slash:comments elemre lesz szükségünk, amihez a slash névteret definiálnunk kell az XML elején. Hasonló a helyzet akkor, ha a szerző nevét egy dc:creator elemben szeretnénk publikálni, szintén meg kell adnunk a névtér feloldását a feed elején:
<channel xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
Ezt így tehetjük meg:
feed.AttributeExtensions.Add( new XmlQualifiedName( "xmlns:dc" ), "http://purl.org/dc/elements/1.1/" );
feed.AttributeExtensions.Add( new XmlQualifiedName( "xmlns:slash" ), "http://purl.org/rss/1.0/modules/slash/" );
Az értékek beszúrását pedig így:
item.ElementExtensions.Add( "slash:comments", null, commentCount );
item.ElementExtensions.Add( "dc:creator", null, userName );
Mindezekből látható, hogy tetszőleges szerkezetű XML-t össze tudunk állítani, az objektumok szabványos sorosításáról a SaveAsRss20 vagy SaveAsAtom10 metódus gondoskodik. Ahhoz, hogy az eredmény valóban szabványos legyen, célszerű használni a CreatePlaintextContent, CreateHtmlContent, CreateAlternateLink stb. metódusokat.
Bár a felhasznált osztályok olyan névtérben találhatóak, amelyek elvileg a WCF részei, ASP.NET esetén nincs szükség arra, hogy WCF endpointokat definiáljunk, közvetlenül használhatjuk ezeket az osztályokat egy HTTP handlerben és a kisorosított XML-t közvetlenül írhatjuk a válasz streambe.