İçeriğe atla

ASP.NET Core 6/Tag Helper'lar/Dahili Tag Helper'lar

Vikikitap, özgür kütüphane

Bu bölümde ASP.NET Core'un sunduğu dahili tag helper'ları göreceğiz. Kendi tag helper sınıflarımızı oluşturabilmemize rağmen çoğunlukla işlerimizi ASP.NET Core'un sunduğu dahili tag helper'larla görürüz.

Dahili tag helper'ları etkinleştirme

[düzenle]

Microsoft'un sunduğu dahili tag helper'lar Microsoft.AspNetCore.Mvc.TagHelpers isim alanındadır. Bu isim alanındaki tüm tag helper sınıflarına erişim hakkı elde etmek için aşağıdaki direktifi ilgili view'a, Views klasöründeki _ViewImports.cshtml dosyasına veya Pages klasöründeki _ViewImports.cshtml dosyasına koyabiliriz.

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<a> etiketine uygulanabilen tag helper'lar

[düzenle]

<a> etiketi HTML'de link oluşturmaya yarar. <a> etiketine uygulanan tag helper'lar sayesinde <a> etiketinin href seçeneğinde belirtilen URL'nin statik olarak değil de, uygulamanın rota yapılandırmasına göre dinamik oluşturulmasını sağlayabiliriz. Bu sayede uygulamanın rota yapılandırması değişse bile üretilen linkler de ona göre değişeceği için linkler sorunsuz bir şekilde çalışmaya devam edecektir. <a> etiketine uygulanabilen tag helper sınıfı AnchorTagHelper'dır. AnchorTagHelper sınıfının desteklediği HTML seçenekleri aşağıda verilmiştir:

asp-action: Linke basıldığında tetiklenecek olan action.
asp-controller: Linke basıldığında tetiklenecek olan action'ı içeren controller. Eğer controller belirtilmezse aktif view'ı hangi controller render'ladıysa o controller seçilir.
page: Linke basıldığında gidilecek olan Razor sayfası. / karekteri ile başlamalıdır.
asp-page-handler: Linke basıldığında gidilecek olan Razor sayfasının handler metodu. Daha önce gördüğümüz üzere Razor sayfaları GET request'leri için birden fazla handler metot içerebilir.
asp-fragment: HTML'de linkin sonuna eklenen ve # karekteriyle başlayan kısmı belirtir. Belirli bir sayfanın belirli bir yerine gitmeye yarar.
asp-host: Üretilecek URL'nin host kısmını belirtir.
asp-protocol: Üretilecek URL'nin protokol kısmını belirtir.
asp-route: URL'yi üretmek için kullanılacak rota ismini belirtir.
asp-route-*: Farklı rota değişkenleri için değer sağlamaya yarar. Örneğin asp-route-id ile id rota değişkeni için değer sağlanır.
asp-all-route-data: Bütün rota değişkenleri için tek bir seferde değer belirtmeye yarar.

[düzenle]

<a> etiketine uygulanan tag helper'lar URL oluştururken aynı zamanda link oluştururlar. Link oluşturmadan URL oluşturmak için Url yardımcısı kullanılabilir. Url yardımcısına controller'lardan, sayfa modellerinden ve view'lardan direkt erişilebilir. Bir view'dan bir örnek:

<div>@Url.Page("/suppliers/list")</div>

Bu örnek Pages/Suppliers klasöründe bulunan List Razor sayfasına URL oluşturur.

string url = Url.Action("List", "Home");

Burası bir controller veya Razor sayfası model sınıfıdır ve Home controller'ının List action'ına URL üretmektedir.

JavaScript tag helper'ı

[düzenle]

HTML'deki <script> etiketlerini oluşturmak için ScriptTagHelper sınıfının temsil ettiği tag helper kullanılabilir. Bu tag helper'ın HTML etiketine eklenebilecek seçenekler aşağıda verilmiştir:

asp-src-include: View'a eklenecek JavaScript dosyalarını belirtmek için kullanılır.
asp-src-exclude: View'dan çıkartılacak JavaScript dosyalarını belirtmek için kullanılır.
asp-append-version: Cache busting amacıyla kullanılır. Kullanımı ileride verilecektir.
asp-fallback-src: JavaScript dosyası bir CDN'den alınıyorsa ve bir sorun nedeniyle alınamadıysa bir fallback JavaScript dosyası belirtmeye yarar.
asp-fallback-src-include: CDN'deki bir sorun nedeniyle JavaScript dosyası alınamadığında kullanılacak JavaScript dosyalarını belirtmeye yarar.
asp-fallback-src-exclude: CDN'deki bir sorun nedeniyle JavaScript dosyası alınamadığında çıkartılacak JavaScript dosyalarını belirtmeye yarar.
asp-fallback-test: CDN'in düzgün çalışıp çalışmadığını ve ilgili JavaScript dosyalarının CDN'den alınıp alınamadığını test etmek amacıyla kullanılır. İlgili CDN'in düzgün çalıştığını gösterecek bir JavaScript kodu içerir.

JavaScript dosyalarının eklenmesi

[düzenle]

JavaScript dosyalarının eklenmesi için çoklu seçim desenleri kullanılabilir. Bu desenler aşağıda verilmiştir:

Desen Örnek Açıklama
? js/src?.js / haricindeki tek bir karakter. Bu örnek js klasöründeki src1.js ve src2.js dosyalarını seçer. Ama src12.js dosyasını seçmez.
* js/*.js / haricindeki bir veya birden fazla karakter. Bu örnek js klasöründeki bütün .js uzantılı dosyaları seçer.
** js/**/*.js Bütün karakterler. Örneğimizde js klasöründeki ve bütün alt klasörlerindeki bütün .js uzantılı dosyalar seçilir.

Örnek:

<script asp-src-include="/lib/jquery/**/*.min.js"></script>

Projemizin wwwroot/lib/jquery klasöründe jquery.js, jquery.min.js, jquery.slim.js ve jquery.slim.min.js olmak üzere 4 dosyanın olduğunu varsayarsak bu kod jquery.min.js ve jquery.slim.min.js'i sayfaya ekleyecektir. Eğer bu kod yerine

<script asp-src-include="/lib/jquery/**/*.min.js" asp-src-exclude="**.slim.**"></script>

Kodunu yazarsak daha önceki seçimden ".slim." ibaresini içeren dosyalar çıkartılacaktır. Bu durumda tek seçilen dosya jquery.min.js olacaktır.

Cache busting

[düzenle]

İstemciye gönderilen JavaScript ve CSS dosyaları çoğu zaman cache'lenir. Çok çeşitli caching mekanizamaları vardır ve bunların çoğu programcının kontrolü dışındadır. Çoğunlukla cache'lenen dosyaların belirli bir süresi vardır, bu süre dolduktan sonra sunucudan yeni CSS veya JavaScript dosyası istenir. Ancak bazen bu süre dolmadan uygulamanın kullandığı CSS veya JavaScript dosyasının versiyonu değişebilir. Eski versiyonla bir süre içerik sunmaya devam etmek sorunlara yol açabilir. Bu sorunun üstesinden gelmek için cache busting denen bir yaklaşım kullanılır. Örnek:

<script asp-src-include="/lib/jquery/**/*.min.js" asp-src-exclude="**.slim.**" asp-append-version="true"></script>

Bu kod tag helper tarafından şuna benzer bir koda çevrilir:

<script src="/lib/jquery/jquery.min.js?v=_xUj-3OJU5yExlq6GSYGSHk7tPXikyn"></script>

Buradaki query string daha önce sunulan dosyanın checksum'ıdır. Sunucuda daima güncel dosyanın checksum'ı tutulur ve link oluşturulurken bu checksum kullanılır, JavaScript dosyası ise bir cache'ten sunulabilir. Örneğin JavaScript dosyalarının bir CDN cache'inde tutulduğunu varsayalım. CDN, URL'ye göre cache'leme yapar. Eğer daha önce talepte bulunduğunuz URL'yle aynı URL'ye talepte bulunursanız CDN cache'lenmiş içeriği döndürecektir. Örneğin 9. taleple 10. talep arasında JavaScript dosyasının güncellendiğini düşünelim. 10. talepte sunucu güncel JavaScript dosyasının checksum'ını HTML dosyasının içine gömüp gönderecektir. İstemci bu sefer yeni checksum ekli bu URL için talepte bulunacaktır. CDN böyle bir URL'yi tanımadığı için akışı sunucuya yönlendircektir. Sunucu güncel JavaScript dosyasını sunacaktır. Sunulan bu JavaScript dosyası CDN'e de kaydedilecektir. Daha sonraki değişmeyen JavaScript dosyası talepleri yine CDN'den karşılanacaktır. Sonuçta sunucudaki JavaScript dosyası güncellenmişse güncel dosya, güncellenmemişse cache'lenen dosya sunulacaktır.

CDN'lerle çalışma

[düzenle]

Cache'lemenin çok farklı şekillerde yapılabileceğini daha önce söylemiştik. İstemciye yakınlığına göre üç farklı cache'leme şeklinden bahsedebiliriz:

  1. Tarayıcıda cache'leme: Tarayıcının daha önce aldığı bir içeriği tekrar alması gerektiğinde tekrar İnternetten alması yerine kendi lokalinde tuttuğu kopyayı kullanmasıdır.
  2. CDN'de cache'leme: İçeriğin asıl sunucu yerine istemciye coğrafi olarak daha yakın bir sunucuda tutulmasıdır.
  3. Sunucuda cache'leme: İçerik yine sunucuda tutulur. Ancak içerik üretilme sürecinden geçmez. Daha önce üretilmiş içerik statik olarak sunulur.

Bu bölümde daha ara bir çözüm olan CDN'lerden (content delivery network - içerik dağıtım ağı) bahsedilecektir. Resimler, JavaScript ve CSS dosyaları gibi statik içerikler sıklıkla CDN'lerde tutulabilir. CDN'lerin temelde iki faydası vardır. İlki, içerik istemciye daha yakın bir sunucudan sunulduğu için web sitesi daha hızlı çalışacaktır, kullanıcının web sitesini kullanma deneyimi daha olumlu olacaktır. İkinci olarak ise sunucu ilgili statik içeriği sunmak için kaynak kullanmadığı için kaynakları daha verimli kullanmış olacaktır. CDN'lerin bu avantajından faydalanmak için örneğin JQuery paketini yüklemek için <script> etiketinin src seçeneğine aşağıdaki linklerden birini koyabilirsiniz.

  • https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js
  • https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
  • https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.map
  • https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.slim.js
  • https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.slim.min.js
  • https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.slim.min.map

jquery.js dosyası kütüphaneninin kendisir. jquery.min.js normal jquery paketiyle aynı işlevselliğe sahiptir, ancak boyutu küçültmek adına beyaz boşluklar ve fonksiyon adları gibi identifier'lar minimum uzunluk seviyesine çekilmiştir. jquery.slim.js standart jquery paketinin sık kullanılmayan bazı işlevlerinin çıkartıldığı daha kompakt bir versiyonudur. jquery.slim.min.js jquery.slim paketiyle aynı işlevselliğe sahip olup dosya boyutunun küçültülmesi adına beyaz boşlukların ve fonksiyon adları gibi identifier'ların minimum uzunluğa çekildiği versiyonudur. Uzantısı .map olan dosyalar aynı paketin asıl versiyonuyla min versiyonu arasında eşleme yaparlar. Dosyanın min versiyonu kullanılmasına rağmen debug sürecinde tam fonksiyon isimlerinin kullanılmasını sağlarlar.

Elbetteki JQuery dışında CDN'den yükleyebileceğiniz başka JavaScript kütüphaneleri de vardır. Bunlar görmek için https://cdnjs.com adresine gidebilirsiniz. Örneğin şimdi jquery.min.js paketini bir view'a yükleyelim:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" 
asp-fallback-src="/lib/jquery/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>

Burada CDN'den jquery.min.js paketinin 3.6.0 versiyonu view'a yüklenmektedir. Eğer CDN'den dosya çekilemiyorsa dahili jquery paketi kullanılacaktır. asp-fallback-test seçeneğine verilen JavaScript ifadesi false döndürürse ilgili kütüphanenin yüklenemediği anlaşılacak ve belirtilen dahili JavaScript dosyasının kullanılması sağlanacaktır. JQuery paketinin doğru yüklenip yüklenmediğinden emin olmak için gönül rahatlığıyla window.jQuerykodunu kullanabilirsiniz. Eğer CDN'deki JavaScript dosyasının yüklenememesi durumunda çoklu seçim desenleriyle birden fazla lokal JavaScript dosyası yüklememiz gerekecekse asp-fallback-src-include ve asp-fallback-src-exclude seçenekleri kullanılabilir.

CSS tag helper'ı

[düzenle]

CSS tag helper'ı JavaScript tag helper'ıyla aynı mantıkla çalışır. LinkTagHelper sınıfı HTML'deki <link> etiketine uygulanır ve <script> etiketindediyle benzer aşağıdaki seçenekleri içerir:

asp-href-include: Eklenen CSS dosyalarını belirtmeye yarar.
asp-href-exclude: Çıkartılacak CSS dosyalarını belirtmeye yarar.
asp-append-version: Cache busting uygulamaya yarar.
asp-fallback-href: Eğer CDN'deki bir sorun nedeniyle CSS dosyası yüklenemiyorsa dahili CSS dosyasını belirtmeye yarar.
asp-fallback-href-include: Eğer CSS dosyası CDN'den yüklenemiyorsa çoklu seçim desenleriyle birden fazla CSS dosyası belirtmeye yarar.
asp-fallback-href-exclude: asp-fallback-href-include seçeneğinin belirttiği kümeden çıkartma yapmaya yarar.
asp-fallback-href-test-class: CDN'in çalışıp çalışmadığının test edilebilmesi için kullanılacak CSS sınıfının belirtilmesini sağlar.
asp-fallback-href-test-property: CDN'in çalışıp çalışmadığının test edilebilmesi için kullanılacak CSS seçeneğinin belirtilmesini sağlar.
asp-fallback-href-test-value: CDN'in çalışıp çalışmadığının test edilebilmesi için kullanılacak CSS değerinin belirtilmesini sağlar.

ScriptTagHelper sınıfında olduğu gibi LinkTagHelper sınıfıyla da çoklu seçim desneleriyle birden fazla CSS dosyası view'a eklenebilir. Örneğin popüler CSS kütüphanesi olan Bootstrap paketini projemize yüklediğimizi varsayalım. Varsayılan durumda çok fazla CSS dosyası wwwroot/lib/bootstrap/css klasöründe tutulacaktır. Bu klasördeki bazı CSS dosyalarını seçip bazılarını seçmemek için view'a aşağıdaki <link> etiketini ekleyebiliriz:

<link asp-href-include="/lib/bootstrap/css/*.min.css"
asp-href-exclude="**/*-reboot*,**/*-grid*,**/*-utilities*, **/*.rtl.*" rel="stylesheet" />

Gördüğünüz gibi çıkartılacak kümeler ayrı ayrı virgülle ayrılmış şekilde belirtilebilmektedir.

CSS dosyalarının CDN'den eklenmesi

[düzenle]

JavaScript dosyalarında olduğu gibi CSS dosyaları da CDN'den eklenebilir. Örnek:

<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css" 
asp-fallback-href="/lib/bootstrap/css/bootstrap.min.css" asp-fallback-test-class="btn"
asp-fallback-test-property="display" asp-fallback-test-value="inline-block" rel="stylesheet" />

Örneğimizde hem CDN'deki CSS dosyası URL'si, hem de eğer CDN çalışamazsa sunucudaki CSS dosyasının yolu verilmiştir. Eğer Bootrstarp paketi etkinleştirildiyse btn CSS sınıfının display seçeneğinin değeri inline-block olacaktır. Eğer btn sınıfının display seçeneğinin değeri inline-block değilse Bootstrap paketi etkinleştirilmemiş demektir, bu da CDN'deki bir sorun nedeniyle ilgili kütüphanenin alınamadığı anlamına gelir.

Resim tag helper'ı

[düzenle]

HTML <img> etiketiyle sayfaya eklenen resimler de birer statik kaynaktır ve bunlar da cache'lenebilir. <img> etiketlerine etki eden tag helper ImageTagHelper sınıfıdır. Örnek:

<img src="/images/city.png" asp-append-version="true" />

Bu örneğimizde resmin cache'lenmiş olduğu durumda orijinal resim değişmişse orijinal resmi, orijinal resim değişmemişse cache'lenmiş resmin alınması sağlanmakatdır.

Cache'leme

[düzenle]

CacheTagHelper sınıfı vasıtasıyla cache'leme yapılabilmektedir. Bu sayede view'daki <cache> ve </cache> arasına alınan her şey birazdan göreceğimiz seçeneklerin belirttiği yapılandırma ayarlarıyla beraber sıfırdan üretilmek yerine statik bir içerik sunar gibi sunulacaktır. <cache> etiketine eklenebilecek şeçenekler aşağıda verilmiştir.

enabled: İçerik cache'lenecek mi? Seçenek sağlanmazsa değeri true kabul edilir. (tipi: bool)
expires-on: İçerik cache'lenmesine ne zaman son verilecek? (tipi: DateTime)
expires-after: İçerik cache'lenmesine ne kadar zaman sonra son verilecek? (tipi: TimeSpan)
expires-sliding:Bu seçenek için bir değer sağlanması halinde içeriğin son kullanıldığı zamandan itibaren belirli bir zaman geçmesi durumunda cache'lemeye son verilir. (tipi: TimeSpan)
vary-by-header: Cache'lenen içeriğin farklı versiyonlarının request header'ına göre seçilmesini sağlar.
vary-by-query: Cache'lenen içeriğin farklı versiyonlarının query string'e göre seçilmesini sağlar.
vary-by-route: Cache'lenen içeriğin farklı versiyonlarının rota değişkenine göre seçilmesini sağlar.
vary-by-cookie: Cache'lenen içeriğin farklı versiyonlarının cookie değişkenine göre seçilmesini sağlar.
vary-by-user: Cache'lenen içeriğin farklı versiyonlarının aktif kullanıcıya göre seçilmesini sağlar.
vary-by: Cache'lenen içeriğin farklı versiyonlarının belirtilen şeye göre seçilmesini sağlar
priority: Cache'lenen içeriğin çnem seviyesini belirtmeye yarar. Cache'leri tutan bellek bölgesinin dolması durumunda ve süresi dolmayan cache'lerin silinmesi gerektiğinde kullanılır.

Örnek kullanım (herhangi bir view'da):

<cache>@DateTime.Now.ToLongTimeString()</cache>

Bu örneğimizde sayfa yenilense bile zaman damgası değişmeyecektir.

Cache'in miadını belirtme

[düzenle]

Kuşkusuz sonsuza dek geçerli olacak bir cache mantıklı olmayacaktır. Bunun yerine cache'lemeyi belirli bir süreyle kısıtlamalıyız. Örnek:

<cache expires-after="@TimeSpan.FromSeconds(15)">@DateTime.Now.ToLongTimeString()</cache>

Bu örneğimizde orijinal içerik üretme periyodu 15 saniyedir. Her 15 saniyede bir orijinal içerik verilecek, diğer kalan bütün zamanlarda son cache'lenmiş içerik verilecektir. Başka bir örnek:

<cache expires-on="@DateTime.Parse("12.12.2024 22:00")">@DateTime.Now.ToLongTimeString()</cache>

Bu örneğimizde cache'in ömrü 12 Aralık 2024 günü saat 22:00'de dolacaktır. Cache için belirli bir zaman belirtildiği zaman cache'in kendini tekrar etme özelliği olmaz. Yeni bir cache kurmak için C# kodu sunucu tarafında değiştirilmelidir. Başka bir örnek:

<cache expires-sliding="@TimeSpan.FromSeconds(5)">@DateTime.Now.ToLongTimeString()</cache>

Bu örneğimizde 5 saniye içinde yapılan bütün request'ler cache'ten karşılacaktır. Eğer son yapılan taleple yeni talep arasında minimum 5 saniye fark oluşursa orijinal içerik sunulacaktır. Orijinal içerik sunulduktan sonra da 5 saniye içinde yapılan talepler cache'ten karşılanacktır. Diğer bir deyişle bu cache de kendini tekrar eden bir cache türüdür.

Cache'in request'e göre değişmesi

[düzenle]

Varsayılan durumda cache'leme request'ten bağımsızdır. İstersek request'teki ayrı bir kritere göre ayrı bir cache tutulmasını sağlayabiliriz. Örnek:

<cache expires-sliding="@TimeSpan.FromSeconds(5)" vary-by-route="action">@DateTime.Now.ToLongTimeString()</cache>

Bu örneğimizde 5 saniyelik sliding bir cache belirtilmektedir. Ancak bu cache her action için farklıdır. Örneğin ilgili view'a Index action'ı üzerinden erişildiyse farklı bir cache, List action'ı üzerinden erişildiyse farklı bir cache tutulacaktır. Bu iki action'ın da aynı view'ı render'lamasını sağlayıp, uygulamayı çalıştırıp, tarayıcınızda farklı action'ları işaret eden iki ayrı sekme aöarsanız cache'leme döngülerinin birbirinden bağımsız olduğunu görürsünüz.

Environment tag helper'ı

[düzenle]

Environment tag helper'ı uygulamanın mevcut çevresine göre view'da belirli kısımların olması veya olmamasını sağlar, EnvironmentTagHelper sınıfıyla temsil edilir. Örnek:

<environment names="development">Uygulama development aşamasında</environment>
<environment names="production">Uygulama production aşamasında</environment>

Burada names seçeneğine virgülle ayrılmış şekilde birden fazla çevre yazılabilir.