Makale Özeti

Bu makalede ASP.NET MVC yapısı içerisinde mimari yapıya uygun olarak site beslemesini nasıl üretebileceğimizi inceleyeceğiz.

Makale

ASP.NET MVC ile site beslemesi (feed) üretmek

Bu makalemizde web sayfalarında standart haline gelen içerik paylaşımını, en çok kullanılan rss ve atom formatlarını kullanarak nasıl gerçekleştirebileceğimize bakacağız.

Rss ve atom yapılarının özelliği platform bağımsız bir şekilde site içeriğini sunmanıza izin vermesidir. .Net framework 3.5 ile framework içerisinde yer almaya başlayan Windows Communication Foundation kütüphaneleri ile rss 2.0 ve atom 1.0 formatında veri üretmemizi sağlayacak sınıflar, framework içerisinde standart olarak gelmeye başladı. Bu makalede ilgili sınıfların kullanım detaylarına girmeyeceğiz ancak bu konu ile ilgili bilgiyi Burak Selim Şenyurt'tun blog yazısında bulabilirsiniz.

Örneğimizi geliştirmeye besleme olarak sunacağımız verimizi hazırlamak ile başlayalım. Bu iş için .Net framework 3.5 ile birlikte, System.ServiceModel kütüphanesinde System.ServiceModel.Syndication namespace'i içerisinde yar alan SyndicationFeed ve SyndicationItem sınıflarından yararlanacağız.

public SyndicationFeed GenerateFeed()

{

var items = new List<SyndicationItem>();

var newsContent =

"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec justo sed odio egestas ultrices. Donec venenatis rhoncus nisi consequat fermentum. Nunc pretium dignissim tellus, vitae dictum nibh tristique vel. Nunc cursus lacinia leo quis pellentesque. Phasellus rutrum magna vel eros feugiat quis tincidunt nunc porta. Nunc vitae tellus sed lacus consequat tristique sed non metus. Aliquam sed faucibus eros. Fusce viverra laoreet ultrices. Sed sed est a enim scelerisque fringilla. Quisque vitae nibh quis metus bibendum blandit. Aenean vestibulum vulputate felis et pharetra. Vivamus ac quam nisi, et viverra arcu. Donec mattis euismod mi vitae molestie. Fusce eget magna justo. Ut a lorem erat, at sollicitudin sapien. Nullam condimentum blandit nibh quis eleifend. Donec blandit elementum tristique. Ut at justo mi. Donec libero dolor, blandit sit amet commodo vitae, fringilla vitae sem. Duis dignissim nulla aliquet massa ultrices sed consequat mi dictum. ";

var item = new SyndicationItem(

title: "Haber 1",

content: newsContent,

itemAlternateLink: new Uri(

Request.Url.AbsoluteUri + "/" + 1),

id: Request.Url.AbsoluteUri + "/" + 1,

lastUpdatedTime: DateTime.Now.ToUniversalTime()

);

item.PublishDate = DateTime.Now.ToUniversalTime();

item.Summary = new TextSyndicationContent(newsContent, TextSyndicationContentKind.Plaintext);

items.Add(item);

var feed = new SyndicationFeed(

"Haber Beslemeleri",

"En son haberler",

new Uri(Request.Url.AbsoluteUri)

);

feed.Authors.Add(new SyndicationPerson("erdem.ergin@gmail.com"));

feed.Language = "TR-TR";

feed.LastUpdatedTime = DateTime.Now;

feed.Items = items;

return feed;

}

Yukarıdaki fonksiyonda ilk önce bir SyndicationItem nesnesi oluşturduk. Bu beslememizdeki bir kayda karşılık geliyor. Canlı sistemde üretmek istediğimiz kayıt sayısı kadar SyndicationItem nesnesi  oluşturmanız gerekecek. Daha sonra beslememizin ana elemanı olan SyndicationFeed nesnesini oluşturup, hazırladığımız SyndicationItem nesnelerini ekliyoruz. Bu fonksiyonda kullandığımız nesnelerin detayları ile ilgili bilgiyi yukarıda belirttiğim Burak Selim Şenyurt'un makalesini inceleyebilirsiniz.

Bu noktada makalemizin ana konusu olan içeriği sunma kısmına geçebiliriz. Sitemizde klasik web sayfası isteklerine html içeren cevaplar dönerken, besleme isteklerine, formata bağlı olarak xml tabanlı yapılarda cevap dönmemiz gerekiyor. Bunun için ASP.NET mimarisinde html'den farklı içerik tiplerinde cevap dönmemizi sağlayan FileResult nesnesinden yararlanacağız.

RSS isteklerinde kullanacağımız ActionResult sınıfımızı oluşturalım.

public class RssResult : FileResult

{

public RssResult() : base("application/rss+xml") { }

private readonly SyndicationFeed _feed;

public RssResult(SyndicationFeed feed)

: this()

{

_feed = feed;

}

protected override void WriteFile(HttpResponseBase response)

{

var formatter = new Rss20FeedFormatter(_feed);

using (XmlWriter writer = XmlWriter.Create(response.Output))

{

formatter.WriteTo(writer);

}

}

}

Bu sınıfımızda constructor'da FileResult sınıfının constructor'ını çağırıyoruz ve sunucudan döneceğimiz içerik tipini belirtiyoruz. Eğer ATOM formatında cevap dönememiz gerekirse içerik tipi olarak "application/atom+xml" kullanmamız gerekiyor. Ayrıca FileResult sınfının WriteFile methodunu ezerek sunucudan dönmek istediğimiz cevabı HtpResponse nesnesine ekliyoruz. Daha önceden oluşturduğumuz SyndicationFeed nesnesini besleme formatına çevirmek için gerekli olan sınıflar System.ServiceModel.Syndication namespace'i altında bulunuyor. RSS 2.0 formatında veri üretmek için SyndicationFeed'imi Rss20FeedFormatter ile formatlamamız gerekiyor. Eğer Atom 1.0 formatında veri üremek isteseydik, Atom10FeedFormatter sınıfını kullanacaktık.

Son olarak besleme içeriğini dönecek Action'larımızı hazırlamamız gerekiyor. Rss içeriği dönecek Action'ımızı aşağıdaki şekilde kodlayabiliriz.

public ActionResult Rss()

{

return new RssResult(GenerateFeed());

}

Fonksiyonumuz çok basit, GenerateFeed fonksiyonu ile SyndicationFeed tipinde nesnemizi üretip onu FileResult'tan türettiğimiz RssResult sınıfına veriyoruz.

Bu noktada uygulamamız http://uygulama/controller/Rss şeklinde gelen isteklere cevap olarak Rss içeriği dönecektir.

Teorik olarak uygulamamız bitmiş gibi dursa da, pratikte bu şekilde kodlanmış bir besleme yapısı canlı ortamda sitemizde performans problemlerine neden olacaktır. Bunun altında yatan nedenleri incelersek:
- Besleme içeriği oluşturacak yapımız veri kaynağımızdan toplu veri çekip bunu işleyeceği için diğer sayfalarımıza oranla sistemimizde daha büyük bir yük oluşturacaktır.
- Ziyaretçilerimiz, beslememizi bu tür içeriği okumak için geliştirilen uygulamalara kaydettiklerinde, bu uygulamalar periyodik olarak web sitemize istek gönderecek böylece bu sayfa üzerinde yük oluşacaktır.

Bu sorunların önüne geçebilmek adına Rss action'ımıza gelen istekleri mümküm olduğunca önbellekten cevaplamak isteriz. Bunu sağlamak için Rss fonksiyonumuza OutputCache attribute'unu ekleyeceğiz.

[OutputCache(VaryByParam = "none", Duration = 300)]

Kullandığımız iki parametrenin anlamlarına bakacak olursak, Duration parametresi ile önbellek'te verinin saniye cinsindan ne kadar süre ile tutulacağını belirliyoruz. VaryByParam parametresi ise querystring'e eklenmiş değerleri dikkate almadan Action'ımıza gelen tüm isteklerin aynı kopya ile cevaplanabileceğini belirtir.

Farklı bir örnek olarak sitemizde yazılar ve yorumlar olarak iki farklı rss verisi sunmak istediğimizi düşünürsek, bunu http://uygulama/controller/Rss?Tip=Yazi ve http://uygulama/controller/Rss?Tip=Yorum şeklinde querystring'den alacağımız değerler ile yapabilirdik ancak bu durumda iki istek için önbellekte farklı kopyalar tutmamız gerekecekti. Bunu sağlamanın yolu ise VaryByParam parametresine "Tip" değerini vermektir. Bu şekilde  her farklı Tip isteği için önbellekte farklı bir kopya tutulacaktır.

Bu makalemizde besleme verilerinin ASP.NET MVC mimarisi içerisinde nasıl sunulabileceğini inceledik. Bunun için öncelikle FileResult sınıfından dönmek istediğimiz veri formatına özel bir sınıf oluşturup, daha sonrasında verinin önbellekte tutulması için yapılması gerekenleri inceldik. Umarım yaralı olmuştur.

Makale kodları