Yazılarımız

Veri Akademi

ASP.NET CORE NEDİR? MİDDLEWARE, ROUTİNG VE MİNİMAL API MANTIĞI

Modern web uygulamalarında performans, güvenlik ve sürdürülebilirlik artık “olsa iyi olur” değil, doğrudan tasarım kriteri. ASP.NET Core da tam bu beklentilerin kesişiminde duran; hafif, modüler ve platform bağımsız bir web geliştirme çatısı olarak öne çıkıyor.

Bu yazıda “ASP.NET Core nedir?” sorusunu sadece tanım düzeyinde bırakmadan; middleware pipeline yaklaşımının arka planını, routing ile isteklerin nasıl doğru noktaya yönlendirildiğini ve son yılların pratik odağı olan Minimal API mantığını bütünlüklü şekilde ele alacağız.

Amacımız: kavramları tek tek ezberletmek değil; istek geldiğinde uygulamanın hangi adımlardan geçtiğini, nerede karar verdiğini ve siz geliştirici olarak bunu nasıl şekillendirebildiğinizi netleştirmek. Yazı boyunca gerçekçi kod örnekleri ve dikkat edilmesi gereken tasarım noktaları da var.

Geliştirici ekranında istek hattı, endpoint akışı ve modüler bileşenlerin bir arada kurgulanması

ASP.NET Core nedir ve neden farklı konumlanır?

ASP.NET Core, .NET ekosisteminin modern web uygulamaları için tasarlanmış, açık kaynak ve çapraz platform çalışan web çatısıdır. Windows dışında Linux ve macOS üzerinde de aynı kod tabanı ile çalışabilir. Bu “platform bağımsızlık” sadece sunucu işletim sistemiyle ilgili değildir; aynı zamanda dağıtım stratejilerinizi, container yaklaşımınızı ve ölçekleme biçiminizi de doğrudan etkiler.

Önceki nesil ASP.NET (özellikle .NET Framework tabanlı) uygulamalarda, IIS’e sıkı bağlar, daha ağır bir çalışma modeli ve daha sınırlı bir modülerlik görülürdü. ASP.NET Core ise küçük parçaları birleştirerek ilerleyen, istek işleme hattını (request pipeline) sizin kurduğunuz bir mimari sunar. Bu sayede uygulama sadece ihtiyaç duyduğu bileşenleri yükler ve daha kontrollü davranır.

Barındırma modeli ve Kestrel’in rolü

ASP.NET Core uygulamaları çoğunlukla Kestrel adlı yüksek performanslı web sunucusu üzerinde çalışır. Kestrel tek başına kullanılabildiği gibi ters proxy (Nginx, Apache, IIS) arkasında da konumlandırılabilir. Böylece TLS sonlandırma, statik dosya servis etme veya gelişmiş yönlendirme senaryoları gibi ihtiyaçlarda altyapı esnekliğiniz artar.

Modüler yaklaşım ve “paket kadar özellik” fikri

ASP.NET Core’un güçlü taraflarından biri; kimlik doğrulama, yetkilendirme, loglama, rate limiting veya response compression gibi bileşenlerin ihtiyaca göre eklenebilmesidir. Bu, geliştiricinin “bütün özellikler açık gelsin” yerine “gerekeni seç” yaklaşımına geçmesini kolaylaştırır. Sonuç olarak hem performans hem de bakım açısından daha dengeli bir yapı kurmak mümkündür.

Sunucu tarafında Kestrel, ters proxy ve uygulama bileşenlerinin katmanlı şekilde konumlanması

Request pipeline: Middleware mantığı ile istek nasıl akar?

ASP.NET Core’da her HTTP isteği, bir “işleme hattından” geçer. Bu hattın her parçasına middleware denir. Middleware’ler, isteği okuyabilir, değiştirebilir, bir sonraki adıma iletebilir veya hattı burada sonlandırabilir. Bu mimari, uygulamanın davranışını açık ve okunur bir sırayla tanımlamanızı sağlar.

Örneğin; bir isteğin önce loglanması, sonra kimlik doğrulaması yapılması, ardından routing ile doğru endpoint’e yönlenmesi ve en sonunda response’un sıkıştırılması gibi adımları, middleware sıralamasıyla kurarsınız. Bu sıralama kritik: yanlış yerde konumlanan bir middleware, doğru çalışsa bile hatalı sonuç üretebilir.

Middleware sırası neden kritik?

Kimlik doğrulama (authentication) middleware’inin, yetkilendirme (authorization) middleware’inden önce gelmesi gerekir; aksi halde kullanıcı kimliği oluşmadan yetki kontrolüne gidilir. Benzer şekilde routing ile endpoint belirlenmeden endpoint’e özel politika veya filtrelerin işletilmesi beklenemez. Bu yüzden pipeline tasarımını “özellik listesi” gibi değil, “akış tasarımı” gibi düşünmek gerekir.

Kısa devre (short-circuit) ve performans etkisi

Bazı middleware’ler isteği erken sonlandırabilir. Örneğin; sağlık kontrolü endpoint’i (health check) ya da statik dosya isteği gibi durumlarda, uygulamanın geri kalanına uğramadan yanıt döndürmek performans kazandırır. Bu “kısa devre” yaklaşımı, doğru yerleştirildiğinde gereksiz iş yükünü azaltır; yanlış kullanıldığında ise beklenmedik davranışlara yol açabilir.

Örnek: Basit bir middleware eklemek

Aşağıdaki örnek, her istek için süre ölçer ve response header’ına yazan basit bir middleware mantığını gösterir. Gerçek sistemlerde bu yaklaşım APM araçlarıyla desteklenebilir; fakat temel fikir aynıdır: isteğin giriş ve çıkış anlarına erişmek.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Use(async (context, next) =>
{
    var start = DateTime.UtcNow;

    await next(); // bir sonraki middleware / endpoint

    var elapsedMs = (DateTime.UtcNow - start).TotalMilliseconds;
    context.Response.Headers["X-Elapsed-Ms"] = elapsedMs.ToString("0");
});

app.MapGet("/", () => "Hello from ASP.NET Core!");

app.Run();

Burada dikkat edilmesi gereken nokta, await next() çağrısının pipeline’ın devam etmesini sağladığıdır. Eğer bu çağrı yapılmazsa, alt adımlar çalışmayabilir ve istek beklenenden farklı şekilde sonlanabilir.


Routing nedir? Endpoint Routing yaklaşımını anlamak

Routing, gelen HTTP isteğinin hangi handler’a (controller action, minimal API endpoint, Razor Page vb.) gideceğini belirleyen mekanizmadır. ASP.NET Core’da modern yaklaşım endpoint routing olarak adlandırılır ve uygulamanın endpoint’lerini merkezi bir şekilde tanımlayıp, istek sırasında uygun endpoint’i seçmeyi hedefler.

Routing sadece URL eşleştirmek değildir. HTTP metodu (GET/POST/PUT/DELETE), route parametreleri, constraint’ler (id sayısal olmalı gibi) ve hatta metadata/policy bağlamı routing kararının parçası olabilir. Bu, özellikle API geliştirmede “doğru endpoint, doğru kurallar” yaklaşımını kolaylaştırır.

Route template, parametre ve constraint kavramları

Örneğin /products/42 gibi bir URL’de 42 değeri route parametresi olarak yakalanabilir. Constraint kullanarak sadece sayısal id kabul edilebilir veya belirli formatlar zorunlu kılınabilir. Bu sayede hatalı istekler daha erken aşamada elenir ve endpoint kodunuz daha temiz kalır.

MapGet / MapPost gibi tanımların routing ile ilişkisi

Minimal API yaklaşımıyla birlikte routing tanımları daha “doğrudan” hale geldi. MapGet bir GET isteği için endpoint ekler, MapPost POST için ekler. Bu tanımlar, endpoint routing tablosuna kayıt düşer ve istek geldiğinde uygun eşleşme seçilir.

Pratik bir örnek:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/products/{id:int}", (int id) =>
{
    return Results.Ok(new { id, name = $"Product-{id}" });
});

app.MapGet("/products/search", (string? q) =>
{
    if (string.IsNullOrWhiteSpace(q))
        return Results.BadRequest(new { message = "q query param is required" });

    return Results.Ok(new { query = q, hits = 3 });
});

app.Run();

Bu örnekte {id:int} ile route constraint tanımlandı. Böylece /products/abc gibi bir istek bu endpoint’e düşmez. Ayrıca /products/search sabit segment olduğu için routing bunu ayrı bir endpoint olarak değerlendirir.


Minimal API mantığı: Ne zaman tercih edilir?

Minimal API, küçük ve orta ölçekli API’ler, mikroservisler, prototipleme veya belirli domain’lerde “sadece endpoint” ihtiyacına hızlı yanıt vermek için tasarlanmış bir yaklaşımdır. Controller tabanlı yapıda sınıflar, attribute’lar ve filtreler üzerinden ilerlerken; Minimal API ile endpoint tanımı daha sade, daha yakın bir kod düzeninde yapılır.

Bu yaklaşım “her şeyi minimal yap” demek değildir. Minimal API, iyi tasarlanmış bir katmanlama ve doğru bağımlılık yönetimi ile birleştiğinde son derece üretken olabilir. Aksi durumda tek dosyada büyüyen, test edilmesi zor ve okunması ağır bir yapıya dönüşebilir. Yani minimal olan, yalnızca yüzey alanıdır; mimari disiplin ihtiyacı ortadan kalkmaz.

Minimal API ile dependency injection (DI) kullanımı

ASP.NET Core’un DI container’ı Minimal API’de de doğal biçimde çalışır. Endpoint parametrelerine servis ekleyerek container’dan çözümleme yaptırabilirsiniz. Bu, iş mantığını bir servise taşıyıp endpoint’i ince tutmak için çok yararlıdır.

Sonuç tipleri ve Results API

Minimal API’de yanıt üretirken Results yardımcılarıyla tutarlı HTTP cevapları döndürmek mümkündür. Bu, hem okunabilirlik hem de standartlaşma açısından önemlidir. Örneğin Results.Ok, Results.NotFound, Results.BadRequest gibi dönüşler hem niyeti açık eder hem de doğru status code üretir.

Örnek: Validation ve servis kullanımıyla daha gerçekçi bir endpoint

Aşağıdaki örnek, basit bir kayıt senaryosunda servis kullanımı, doğrulama ve farklı status code’ları gösterir. Küçük bir API’de bile bu disiplin, uzun vadede bakım maliyetini düşürür.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<IUserStore, InMemoryUserStore>();

var app = builder.Build();

app.MapPost("/users", (CreateUserRequest req, IUserStore store) =>
{
    if (string.IsNullOrWhiteSpace(req.Email))
        return Results.BadRequest(new { message = "Email is required." });

    if (!req.Email.Contains("@"))
        return Results.BadRequest(new { message = "Email format is invalid." });

    var created = store.Create(req.Email.Trim());

    return Results.Created($"/users/{created.Id}", created);
});

app.MapGet("/users/{id:guid}", (Guid id, IUserStore store) =>
{
    var user = store.Find(id);
    return user is null ? Results.NotFound() : Results.Ok(user);
});

app.Run();

record CreateUserRequest(string Email);

interface IUserStore
{
    UserDto Create(string email);
    UserDto? Find(Guid id);
}

class InMemoryUserStore : IUserStore
{
    private readonly Dictionary<Guid, UserDto> _db = new();

    public UserDto Create(string email)
    {
        var dto = new UserDto(Guid.NewGuid(), email, DateTime.UtcNow);
        _db[dto.Id] = dto;
        return dto;
    }

    public UserDto? Find(Guid id) => _db.TryGetValue(id, out var u) ? u : null;
}

record UserDto(Guid Id, string Email, DateTime CreatedAtUtc);

Burada endpoint “ince”, iş kuralı “servise yakın” ve HTTP cevapları “açık”. Bu temel yaklaşım, Minimal API kullanırken kodun büyümesine karşı iyi bir sigorta olur. Ayrıca test edilebilirliği artırmak için store yerine gerçek hayatta repository + database entegrasyonu kullanılabilir.


Middleware + Routing + Minimal API birlikte nasıl düşünülür?

Bu üç kavram, uygulamanın istek karşılayan tarafının üç ayrı katmanını temsil eder: Middleware pipeline istek akışını yönetir, routing istek için hedef endpoint’i seçer, Minimal API ise endpoint’in tanım biçimidir. Bu parçaların birlikte uyumlu çalışması, uygulamanın davranışını öngörülebilir kılar.

Örneğin; global loglama ve hata yakalama middleware seviyesinde ele alınır. Yetkilendirme bazı senaryolarda global olabilir, bazı senaryolarda endpoint metadata’sına bağlanır. Routing ile endpoint seçildikten sonra, Minimal API handler’ı çalışır ve sonuç üretir. Bu akışın zihinde netleşmesi, “neden 404 dönüyor?” veya “neden authorization çalışmadı?” gibi sorunları çok daha hızlı çözmenizi sağlar.

Tipik bir pipeline sıralaması

  • Hata yakalama ve standart hata yanıtı üretimi
  • HTTPS yönlendirme ve güvenlik başlıkları
  • Statik dosyalar (varsa) ve kısa devre senaryoları
  • Routing (endpoint seçimi için hazırlık)
  • Authentication ve Authorization
  • Endpoint’lerin çalıştırılması

Bu sıralama her projede aynı olmak zorunda değil; fakat mantık aynı: önce temel güvenlik ve çerçeve adımları, sonra yönlendirme ve kimlik/yetki, en sonda iş mantığı.


Controller tabanlı API mi, Minimal API mi? Seçim kriterleri

Controller tabanlı yapı, olgun bir ekosistem ve güçlü organizasyon avantajları sunar: filtreler, attribute’lar, action bazlı yapı, model binding gelenekleri ve özellikle büyük ekiplerde standartlaşma kolaylığı. Minimal API ise daha düşük seremonisiyle, daha hızlı gelişim ve daha küçük yüzey alanı hedefler.

Minimal API’nin güçlü olduğu senaryolar

Mikroservisler, basit CRUD servisleri, internal servisler veya gateway arkasında çalışan küçük API’ler Minimal API ile hız kazanabilir. Ayrıca endpoint sayısı sınırlı ve davranışı net olan servislerde “fazla yapı” kurmadan ilerlemek verimlidir.

Controller yaklaşımının öne çıktığı senaryolar

Çok sayıda endpoint, karmaşık cross-cutting ihtiyaçlar, geniş ekipler ve uzun ömürlü ürün geliştirme süreçlerinde controller yapısı daha kolay yönetilebilir olabilir. Bunun nedeni, yerleşik pattern’lerin daha oturmuş ve araç desteğinin daha güçlü olmasıdır.

Aslında çoğu ekip “ikisini birlikte” de kullanır. Örneğin bazı hızlı internal endpoint’ler Minimal API ile tanımlanırken, ana işlevler controller düzeninde kalabilir. Seçim bir “din” değil, bir mühendislik kararı olmalı.


Performans, bakım ve test edilebilirlik açısından ipuçları

ASP.NET Core’un performans potansiyeli yüksek; ancak gerçek kazanım, doğru yapılandırma ve doğru sınırlar koymakla gelir. Middleware’leri gereksiz yere çoğaltmak, her istekte ağır işler çalıştırmak ya da endpoint kodunu servis yerine endpoint içine gömmek, bakım maliyetini artırır.

Endpoint’leri ince tut, işi servise taşı

Minimal API’de de olsa controller’da da olsa; endpoint’in görevi istek/yanıt sınırını yönetmek olmalı. Validasyon, domain kuralları, veri erişimi gibi unsurlar servis/repository gibi bileşenlere taşındığında test etmek kolaylaşır. Bu yaklaşım, kodun okunabilirliğini yükseltir ve değişiklikleri daha güvenli hale getirir.

Gözlemlenebilirlik: loglama ve ölçüm

Üretimde sorun çözmenin anahtarı gözlemlenebilirliktir. Uygun log seviyeleri, korelasyon id’leri, hatalarda standart payload, metrikler ve izler (trace) kritik değer taşır. Middleware katmanı, bu tür çapraz kesen ihtiyaçlar için en doğal noktadır.

Güvenlik: varsayılanları iyi bil

HTTPS kullanımı, güvenlik başlıkları, rate limiting, kimlik doğrulama şemaları ve yetkilendirme politikaları gibi konular “sonradan eklenir” diye düşünülmemeli. Minimal API sade görünse de güvenlik ihtiyaçları ortadan kalkmaz; tam tersine daha görünür bir disiplin gerektirir.

Kod düzeninde minimal endpoint tanımları, servis katmanı ve güvenlik politikalarının birlikte organize edilmesi

Öğrenme yolu: Bu konuyu nasıl pekiştirirsiniz?

Kavramları öğrenmenin en hızlı yolu, küçük bir örnek uygulamayı adım adım büyütmektir. Önce iki endpoint ile başlayın, ardından bir middleware ekleyin, routing constraint’leri deneyin, sonra DI ile servis katmanını dahil edin. Bu sırada her adımda “istek hattı”nı zihninizde canlandırmaya çalışın.

Özellikle şu pratikler öğrenmeyi hızlandırır: bir middleware’i bilinçli olarak yanlış sıraya koyup sonucu gözlemek, route template’lerini değiştirip eşleşmeyi test etmek, Minimal API endpoint’lerini birden çok dosyaya bölerek düzen kurmak. Bu çalışmalar, teoriyi deneyime dönüştürür.

Eğer daha sistematik bir ilerleme isterseniz, uygulamalı örnekler ve kurumsal pratiklerle yapılandırılmış bir içerik için ASP.NET Core eğitimi sayfasına göz atabilirsiniz. Böylece middleware, routing ve Minimal API yaklaşımını gerçek proje senaryoları üzerinden pekiştirebilirsiniz.


Kısa özet

ASP.NET Core, modern web geliştirmede modülerlik ve performansı bir araya getirirken; middleware yaklaşımıyla istek akışını kontrol etmenizi, endpoint routing ile doğru hedefe yönlenmenizi ve Minimal API ile daha sade endpoint tanımları yapmanızı sağlar. En iyi sonuçlar, bu parçaları birlikte düşünerek; doğru sıralama, temiz katmanlar ve ölçülebilir bir operasyon yaklaşımıyla elde edilir.

 VERİ AKADEMİ