Erhan Ballıeker

Asp.Net Core 2.0’a Giriş – Bölüm 4 (Startup.cs, Configure, Middleware hakkında)

Selamlar, Asp.Net Core 2.0 Giriş seri postlarından bu bölümde Startup.cs deki Configure metodundan ve Middleware yapısından bahsedeğim. Middleware yapısı çok Asp.Net Core için çok önemli bir değişiklik ve bunun detaylarına ilerleyen postlarda gireceğiz.

Startup.cs deki Configure metodunun yaptığı iş şudur; Asp.Net Core projenizdeki Http Request pipeline nını konfigüre etmek. Peki ne demek bu Pipeline ı konfigüre etmek bunu aşağıdaki resimle bir inceleyelim. Klasik Asp.Net projelerinde Request in izlediği yol çok uzun ve karmaşıkça idi.Sizin belkide hiç kullanmayacağınız birçok yapıdan request geçiyor ve sizin elinize o şekilde ulaşıyordu. Ama aşağıdaki resimde göreceğiniz gibi, Asp.Net Core pipeline nına siz ne eklerseniz middleware olarak sadece o yapılardan geçecek request. Hiç bir middleware eklenmediğinde hiç birşey olmayacak. Bir önceki örneğimizdeki tek bir middleware eklenirse sadece o middleware den geçecek.

pipeline

Asp.Net Core projelerinde resimde görebileceğiniz gibi, koca bir MVC framework pipeline ı bile ayrıca projeye middleware olarak ekleniyor eğer istenirse. Size kalmış, MVC framework ün imkanlarından faydalanacak olanlar pipeline a bunu ekleyebilir, Bunun öncesinde kendi yazdıkları yada built-in gelen middleware lerden Authentication middleware ini koyup, static file ları serve etmek için (css,javascript,images vs..) Static Files Middleware ini pipeline a ekleyebilirler.

HttpRequest, eklediğiniz sırada middleware lerden geçerek, son middleware den sonra aynı şeklide geri dönerek tüm middleware lerden geçip browser a ulaşır. Bu requestin middleware lerdeki akışı sırasında WebServer feature larına ulaşma imkanı veriyor Asp.Net Core uygulamamız. Bir de daha büyük resimde request in browserdan uygulamamıza gelip tekrar browser a geri döndüğü akışa bakalımpipeh.Bu resmi adım adım izleyecek olursak, sırası ile şunlar oluyor.

  • Request browserdan External Web Server a (bu resimde IIS kullanıldığı varsayıldı, ama bu Nginx, Apache olabilir.) ulaşır.
  • External Web Server (IIS) dotnet runtime çalıştırır.
  • dotnet runtime, CLR ı load edip, sizin Application nınızdaki entry point (Program.cs deki Main() matodu ) i arar ve çalıştırır.
  • dotnet runtime Application ı çalıştırdıktan sonra Internal Web Server olan Kestrel ayağa kalkar.(Kestrel olmak zorunda değil, ama internal bir web server için çok çok iyi bir seçenek çünkü hem cross platform bir web server, hem performansı çok iyi).
  • Main metodunuz çalıştıktan sonra, WebHostBuilder ilgili ayarlar ile ayağa kalkar, Startup dosyası ile beraber uygulamanız konfigüre edildikten sonra, HttpRequest, IIS den Kestret’e yönlendirilir.
  • Startup dosyasındaki eklenen middleware lerinizden geçen request tekrar Kestrel e ulaşır, Kestrel,  External Web Server a response u iletir ve sonunda response browser a gelir.

Bu eski System.Web yaklaşımından çok daha verimli ve çok daha resource friendly dir. Klasik Asp.Net projelerinin Windows bağımlı olma sebebi zaten System.Web idi. System.Web assemly IIS e bağlı, IIS de, Windows a bağlıydı. Bu yüzden asp.Net projelerimiz windows dışında işletim sistemlerinde çalışamıyordu.

Şunu da belirtmekte fayda var. External bir web server a mutlaka ihtiyacınız yok aslında. Ama Kestrel çok performanslı ve cross platform bir web server olsada, IIS,Nginx, Apache gibi tam donanımlı web serverlar kadar yetenekli değil, bu yüzden zorunlu olmamakla beraber yüksek ihtimalle bir external web server kullanıyorsunuz. 🙂

Peki özet teorik bilgiden sonra uygulamamıza geri dönelim. ikinci bir middleware ekleyip, requestin oradan geçişlerini loglayarak, middleware yapısının çalışma şeklini iyice anlamaya çalışalım.

Startup.cs dosyasında ki Configure metodunda aşağıdaki değişiklikleri yapalım.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILogger logger)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseStaticFiles();

            app.Use(async (context, next) =>
            {
                logger.LogInformation("First middleware working BEFORE second middleware");
                var serviceProvider = context.RequestServices;
                var userService = serviceProvider.GetRequiredService();
                var users = await userService.GetUsers();
                await context.Response.WriteAsync($"Hello World! - UserCount: {users.Count}");
                await next();
                logger.LogInformation("First middleware working AFTER second middleware");
            });

            app.Run(async (context) =>
            {
                logger.LogInformation("second middleware working");
                await context.Response.WriteAsync("Second middleware done!");
            });
        }

Kod tarafında yaptığımız değişiklikler şunlar;

  1. Configure metoduna ILogger<Startup> objesini inject ediyoruz. Bu daha Default WebHostBuilder konfigüre edilirken oluşturulup uygulamamıza bizim için register edilmiş oluyor Asp.Net Core tarafından
  2. İlk middleware deki app.Run metodunu app.Use olarak değiştiriyoruz. Çünkü Run metodu gelen request i shortcut yapıp sonraki middleware lere iletmeden geri döner. Use metodunda ise, context dışında ikinci bir parametre olarak RequestDelegate objesi gelir(bir sonraki middleware delegesi olarak). buna next  adını verdik, tüm işlemlerimiz bittikten sonra bu delegate i await ediyoruz. Tam bu noktada ikinci middeware miz çalışmaya başlar.
  3. Logları koyduğumuz yerlere dikkat ediniz. Biliyoruz ki middleware ler, uygulamaya eklendiği sırada request leri karşılar, tam tersi sırada da response ları karşılarlar. Projeyi çalıştırdığımızda logların nasıl bir sırayla basılacağına bakalım.

Bu sefer External web server kullanmadan sadece Kestrel i yani Internal Web Server ı kullanarak bu işlemi yapalım. Bunun için Visual Studio da, Run butonun yanındaki oku tıklayıp, IISExpress yerine projenin adının olduğu seçeneği seçmemiz yeterli (örneğimizde MeetupAspNetCore). Bu IIS Express i değil doğrudan Kestrel üzerinden requestleri karşılamamızı ve browser a dönmemizi sağlayacak. Uygulamayı çalıştırıp çıktımıza bakalım.

mware

resimde de göreceğiniz gibi, önce birinci middleware çalıştı, await next() dediğimiz anca ikinci middleware in logu basıldı, ikinci middleware de işini tamamladıkan sonra response geri dönerken,birinci middleware de await next(), dediğimiz yerden sonraki kod bloğunda yazılan log çalışmış oldu.

Bu yazımızı da burada tamamlayabiliriz. Middleware lerden kısaca bahsetmiş olduk, bir AspNet Core projesine gelen request in tüm akışını inceledik ve middleware lerin çalışma şeklini örnekledik.

Asp.Net Core 2.0 yazı serimizde artık temel noktaları gördük diyebiliriz.  Ama henüz Introduction ı tamamen yaptık dememiz için çok şey var 🙂

Bir sonraki yazıda görüşmek üzere.