.NET 6 – WebApplication İle Middleware Pipeline’ını İnceleyelim
Merhaba,
Bu içeriğimizde .NET 6’da ki WebApplication nesnesinin arkasındaki koda bakacak, middleware ve endpointlerin nasıl yapılandırıldığına odaklanıyor olacağız.
Önceki .NET 6 – WebApplicationBuilder’ı İnceleyelim başlıklı makalede açıklandığı gibi uygulama yapılandırmasının yapıldığı yer çoğunlukla WebApplicationBuilder‘dır.
WebApplication ise üç ayrı işlev için operasyonel sorumluluk üstlenmektedir;
- IApplicationBuilder arayüzünü uyguladığı için middleware pipeline’ı burada şekillendirilip, yapılandırılmaktadır. Yani middleware şeması bu nesne üzerinden çıkarılmakta ve tetiklenme sıralaması bu nesne üzerinden ayarlanmaktadır.
- IEndpointRouteBuilder arayüzünü uyguladığı için
MapGet
,MapRazorPages
vs. gibi metotlar aracılığıyla endpointler yapılandırılmaktadır.var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();
- IHost arayüzünü uyguladığından dolayı
Run
metodu eşliğinde uygulama başlatılmaktadır.
WebApplicationBuilder nesnesinin
Build
metodu tetiklendiğinde bir generic host instance’ı oluşturulur ve bu WebApplication türünde geri döndürülür.
WebApplication Nesnesi Başlatma ve Middleware Pipeline’ı Oluşturma
Web uygulamasını başlatmanın standart yolu WebApplication nesnesi üzerinden Run()
ya da RunAsync()
metotlarından birini çağırmaktır. Bu metotlar nihai olarak IHost.StartAsync
metodunu tetikler ve böylece aşağıdaki görseldeki karmaşık metot etkileşimlerinin başlamasına vesile olurlar.
Yukarıdaki şemada görüldüğü üzere Host’un ayağa kaldırılması sırasının bir parçası olarak IHostedService çalıştırılmaktadır. Bu middleware’in oluşturulduğu ve Kestrel sunucusunun dinlenmeye başlandığı zamandır.
Aynı şekilde görseldeki GenericWebHostService ise middleware pipeline’ının oluşturulduğu ve uygulamanın çalıştırılmak için Kestrel’e gönderildiği yerdir.
Bu süreç açısından, WebApplication‘ı generic host ile karşılaştırırsak eğer herhangi bir fark bulunmamaktadır.
WebApplication Middleware Pipeline
WebApplication generic host’a kıyasla çeşitli middleware’ler barındırmaktadır. WebApplicationBuilder ise varsayılan olarak Kestrel sunucusunu yapılandırır, HostFiltering Middleware‘ini ekler ve IIS entegrasyonunu etkinleştirir. Bunlara ek olarak WebApplicationBuilder nesnesi ekstradan middleware yapılanmasını kurar.
Şimdi bir Asp.NET Core uygulamasında middleware yapılanmasının nasıl kurulduğunu adım adım inceleyerek devam edelim.
- Empty(Boş) Pipeline
Öncelikle uygulamaya herhangi bir middleware veya endpoint eklemeksizin incelemede bulunarak başlayalım.Aşağıdaki kod bloğunu incelerseniz eğer;
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.Run();
Bu kod, kurulumun en temelidir ve aşağıdaki middleware pipeline’ı ile işlemektedir.
- HostFilteringMiddleware
- DeveloperExceptionPageMiddleware
- WebApplication nesnesinin ApplicationBuilder property’sinden oluşturulmuş bir middleware
Yukarıdaki middleware pipeline’ını yandaki gibi şemalaştırabiliriz. Burada DeveloperExceptionPageMiddleware‘inin artık development ortamında otomatik olarak eklendiğine dikkatinizi çekerim.
Açıkçası varsayılan middleware’e sahip bir uygulama pek kullanılmamaktadır. Haliyle temeli bu şekilde attıktan sonra biraz middleware ekleyerek gözlemlerimize devam edelim.
- Ekstra Middleware’e Sahip Uygulama
Şimdi aşağıdaki gibi varsayılan yapının üzerine birkaç middleware ekleyerek gözlemlemede bulunalım.var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.Run();
Yukarıdaki çalışmada default olan üç middleware’in üzerine ‘UseHttpsRedirection’ ve ‘UseStaticFiles’ middleware’leri eklenmiştir. Haliyle son durum aşağıdaki gibidir;
- HostFilteringMiddleware
- DeveloperExceptionPageMiddleware
- Aşağıdakileri içeren WebApplication nesnesi;
- HttpsRedirectionMiddleware
- StaticFilesMiddleware
- Endpoint Tanımlama
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.MapGet("/", () => "Laylaylom galiba sana göre sevmeler..."); app.Run();
Yukarıdaki gibi
MapGet
metodu ile eklenen endpoint’ler, WebApplication nesnesinin endpoint datasources koleksiyonuna eklenmektedirler.
Ve nihai olarak EndpointMiddleware‘i eklenerek middleware pipeline ayağa kaldırılmaktadır.
- HostFilteringMiddleware
- DeveloperExceptionPageMiddleware
- Aşağıdakileri içeren WebApplication nesnesi;
- HttpsRedirectionMiddleware
- StaticFilesMiddleware
- EndpointMiddleware
Burada
UseRouting
(RoutingMiddleware) middleware’ini incelememizin sebebi, bazı middleware’lerin UseRouting‘den önce çağrılması gerektiğidir. Haliyle RoutingMiddleware’inden önce çağrılması gereken bir middleware varsa ne yapılması gerekmektedir? gelin inceleyelim…
Bunun için yapılması gereken tek şey UseRouting
middleware’inin açıkça çağrılıp, devreye sokulmasıdır.
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.MapGet("/", () => "Laylaylom galiba sana göre sevmeler..."); app.Run();
Böylece ilgili middleware’ler aşağıdaki gibi şekillenecektir.
- HostFilteringMiddleware
- DeveloperExceptionPageMiddleware
- Aşağıdakileri içeren WebApplication nesnesi;
- HttpsRedirectionMiddleware
- StaticFilesMiddleware
- RoutingMiddleware
- EndpointMiddleware
UseRouting
middleware’i yazıldığında ana/main middleware pipeline’ı ile WebApplication nesnesinin ApplicationBuilder pipeline’ı arasında genel düzenin korunması için WebApplicationBuilder bir işlevsellik göstermektedir. Bu işlevsellik, genel düzeni korumak üzere generic host’a dönmek gerektiğinde ortaya çıkacaktır.
EndpointMiddleware,
MapGet
vs. gibi metotlar eşliğinde ya da WebApplicationBuilder nesnesi ile otomatik ekleniyor olasa da UseEndpoints
metodu eşliğinde de manuel bir şekilde çağrılarak, eklenebilmektedir.
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.MapGet("/", () => "Laylaylom galiba sana göre sevmeler..."); app.UseEndpoints(endpoint => endpoint.MapGet("/x", () => "doldur be meyhaneci boş kalmasın kadehim")); app.Run();
Haliyle yukarıdaki inşa ile aşağıdaki middleware yapılanması elde edilecektir.
- HostFilteringMiddleware
- DeveloperExceptionPageMiddleware
- Aşağıdakileri içeren WebApplication nesnesi;
- HttpsRedirectionMiddleware
- StaticFilesMiddleware
- RoutingMiddleware
- EndpointMiddleware
- EndpointMiddleware
Yukarıdaki davranış ile endpoint’leri doğrudan hem WebApplication‘da hem de EndpointMiddleware‘in çağrısında kaydetmiş oluyoruz.
Burada dikkat edilmesi gereken önemli bir nokta vardır, o da;
UseEndpoints
middleware’i manuel kullanılıyorsa kesinlikleUseRouting
middleware’i de manuel çağrılmalıdır. Aksi taktirde hata alınacaktır.
Nihai olarak;
WebApplication nesnesi üzerinden yapılan çalışmalarda middleware pipeline’ının nasıl ve ne şekilde oluşturulduğunu görmüş ve incelemiş olduk. Böylece artık .NET 6 ile geliştirilen web uygulamalarında, konfigürasyon yapılanmasında neyin ne olduğuna ve ne şekilde davranış sergilediğine tam olarak vakıf bir şekilde geliştirmeler yapabilir ve nimetlerinden daha bilinçli faydalanabiliriz.
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…