SelamünAleyküm geçtiğimiz yazıda .Net Core'un dosya yapısından bahsetmiş olduk bu yazımızda ise .Net Core da Middleware konusunu ele almış olacağız.
Middleware Nedir?
Middleware, Request (İstek) ile Response (Yanıt) pipeline'si arasında kalan uygulamamızın, istekler karşısında nasıl tepki vereceğini belirleyen yapılardır. Middleware'ler uygulama açılırken pipeline'nin hangi sıraya göre işleneceğini belirler. Bu sebeple uygulamamıza Middleware eklerken sırasına çok dikkat etmek gerekir. Çünkü eklediğiniz sıraya göre Middleware'leriniz çalışacaktır.
Örneğin, Configure metodunuza routing işlemlerinin, kimlik doğrulamasının, statik dosya yönetimi gibi işlemlerin olduğu Middleware'ler yazabilirsiniz. Bu yazdığınız Middleware'ler, sizin uygulamanızı işlenme sırasına göre şekillendirecektir.
Şekilde de görüleceği üzere istek, ilk Middleware-1'e gelir. Middleware-1'de Next();'i görene kadar işlemlerini yapar ve sonraki adıma geçer. Daha sonra MiddIeware-2'ye gelir. Aynı şekilde Middleware-2'de de Next();'i görene kadar işlemler yapılır ve Next(); ile sonraki adıma geçilmiş olur. Middleware-3 ise çalıştırılacak son Middleware'dir. Middleware-3'te yapılacak işlemleri yapar ve geriye döner. Geri dönüşte ilk etapta Middleware-2'de başka işlem varsa onu yapar. Sonra Middleware-l'e bakar, buradaki işlemleri de yapıp yanıt olarak kullanıcıya döner.
public void Configure (IAppIicationBui1der app)
{
app.UseStaticFiles(); //Statik Dosyalar
app.UseAuthentication(); //Kimlik Doğrulaması
app.UseMvcWithDefaultRoute(); //MVC İçin Varsayılan Route
}
Yukarıdaki kodda da görüleceği üzere statik dosyalarımızı okuyan, kimlik doğrulaması yapan, MVC'de kullanılması için varsayılan olarak route vb. birçok Middleware'yi uygulamamıza ekleyebiliriz.
Uygulamamıza Middleware eklerken en çok kullanacağımız yöntemlerin başında gelir. Middleware içinde next() kullanarak bir sonraki Middleware'ye geçmesini sağlayabiliriz.
Misalen, Startup sınıfının içindeki Configure metodunun içini aşağıdaki gibi dolduralım.
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
await Context.Response.WriteAsync("1.Use --> 1.Data \n");
await Next();
await Context.Response.WriteAsync("1.Use --> 2.Data \n");
});
app.Use(async (context, next) =>
{
await Context.Response.WriteAsync("2.Use --> 1.Data \n");
await Next();
await Context.Response.WriteAsync("2.Use --> 2.Data \n");
});
}
Uygulamamızı çalıştıralım.
Sonuç olarak yukarıdaki ekran çıktısını alacağız. Uygulamamız ilk olarak Configure metodunun içindeki app.Use'nin içine girmiştir. Orada ekrana yazdırmak istenen "1.Use --> 1.Data \n" yazısını yazmıştır. Sonra uygulamamız next() satırına geçince ikinci app.Use komutuna girmiştir. Burada ekrana yazılmak istenen string ifadelerini ekrana yazmıştır. İkinci app.Use komutunda işi bittikten sonra birinci app.Use komutuna geri dönmüştür ve burada kalan diğer bir işlem olan "1.Use --> 2.Data \n" string ifadeyi ekrana yazmıştır.
Middleware'ler arasında kısa devre yapma özelliği gösterir. Uygulama bu Middleware'ye geldiği zaman app.Run komutunun içerisindeki işlemleri yapar ve uygulamamız sonlanır.
public void Configure(IApplicationBuilder app)
{
app.Run(async context =>
{
await Context.Response.WriteAsync("1.Use --> 1.Data \n");
});
app.Run(async context =>
{
await Context.Response.WriteAsync("2.Use --> 1.Data \n");
});
}
İki adet app.Run komutu çalıştırmamıza rağmen sadece ilkini yazmıştır ve uygulamamız kısa devre yaparak sonlanmıştır.
Uygulamamızda bir path yakalamamız gerekiyorsa app.Map komutunu kullanırız.
public void Configure(IApplicationBuilder app)
{
app.Map("/haberler", internalApp =>
{
internalApp.Run(async context =>
{
await context.Response.WriteAsync("/haberler adresi ile gelindi");
});
});
}
Tarayıcımızın Url'ine haberler yazdığımızda app.Map komutu, bunu yakalayıp Middleware'de geçen işlemleri yerine getirecektir.
Gelen istek app.MapWhen komutu ile bir koşul türü tanımlayabiliriz. Bu koşul sağlanısa bu Middleware'nin içine girmiş olur.
public void Configure(IApplicationBuilder app)
{
app.MapWhen(x => x.Request.Method == "GEt", internalApp =>
{
internalApp.Run(async context =>
{
await context.Response.WriteAsync("HTTPGET isteği yapıldı.");
});
});
}
Kodu çalıştırdığımızda, tarayıcı varsayılan olarak HTTPGET isteği yapacağından "HTTPGET isteği yapıldı." yazısını yazacaktır.
Şimdi daha karışık bir örnek yapalım.
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
await Context.Response.WriteAsync("1.Use --> 1.Data \n");
await Next();
await Context.Response.WriteAsync("1.Use --> 2.Data \n");
});
app.Map("", internalApp =>
{
internalApp.Run(async context =>
{
await context.Response.WriteAsync("/ adresi ile gelindi \n");
});
});
app.MapWhen(x => x.Request.Method == "GEt", internalApp =>
{
internalApp.Run(async context =>
{
await context.Response.WriteAsync("HTTP GET request'te bulunuldu \n");
});
});
app.Run(async context =>
{
await context.Response.WriteAsync("Run-1 \n");
});
}
Kodumuzu çalıştıralım.
Görüldüğü gibi uygulamamızda ilk etapta app.Use komutu çalıştı ve next(); komutunu görünce bir sonraki Middleware komutuna geçti. Bir sonraki Middleware de path yakalama işini yapan app.Map komutu çalıştı. Bundan sonra next diye bir komut gelmediğinden bir sonraki Middleware'ye geçiş Yapmadı. Bir önceki Middleware'de kalan işlemleri tamamlayıp kullanıcıya geri dönüş yapmış oldu.
Bizde uygulamalarımızda istek ve yanıt arasına gelecek Middleware'ler yazıp işleme tabi tutabiliriz.
Misalen, örneğimizde gelen bütün isteklerin o anki zamanını bir metin dosyasna yazdıralım. time.txt isminde bir dosya oluşturalım. (Projeye sağ tık Add / New Item / Text File şeklinde ekleyebilirsiniz.)
Projemizde Middlewares adında bir klasör oluşturalım. İçine RequestTimeMiddleware isminde bir class dasyası oluşturalım. Oluşturulan class dasyamıza Middleware'de yapılacak işlemleri yazalım.
using Microsoft.AspNetCore.Http;
using System;
using System.IO;
using System.Threading.Task;
namespace örnek_proje.Middlewares
{
public class RequestTimeMiddleware
{
private readonly RequestDelegate _next;
public RequestTimeMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
File.AppendAllText("time.txt", DateTime.Now.TimeOfDay.ToString() + Environment.NewLine);
await _next(context);
}
}
}
time.txt dosyasına her request'te o anki zamanı yazacak kodu yazdık.
Şimdi de oluşturduğumuz RepuestTimeMiddleware class'ına ulaşacak Extension metodumuzu yazalım. Bunun için Middlewares klaörü altına RequestMiddlewareExtension isimli bir class dosyası oluşturup, bu class'ı static olarak işaretleyelim.
using Microsoft.AspNetCore.Builder;
using System;
using System.Collections.Generic;
using Systm.Linq;
using System.Threading.Tasks;
namespace CoreExamp1e.Middlewares
{
public static class RequestMiddIewareExtensions
{
public static IApp1icationBui1der UseRequestTime(this IApp1icationBuilder builder)
{
return builder.UseMiddIewareQRequestTimeMidd1eware»();
}
}
}
Şimdi de bu Extension metodumuzu Startup sınıfının altındaki Configure metodunda kullanalım ve app.Run ile ekrana "Program sonu" yazalım.
public void Configure (IAppIicationBuilder app)
{
app.UseRequestTime();
app.Run(async (context) =>
{
await context.Response.WriteAsync("Program sonu");
});
}
Uygulamamızı çalıştıralım ve tarayıcı ekranında birkaç kez refresh edelim. buraya resim ekle. Görüldüğü gibi yazdığımız Middleware sayesinde her yapılan istek time.txt metin dosyasına yazdırıldı.
Bu konumuzda Middleware konusunu incelemiş olduk bu konuda ilgilenenlerin faydalanması ümidi ile.
Blog Listesi