Mert Özen Her Satırda Daha İleri
Anasayfa Blog İlk projeyi kurma: proje yapısı, Program.cs ve minimal hosting modeli
Backend .NET Core Web API — #02

İlk projeyi kurma: proje yapısı, Program.cs ve minimal hosting modeli

Mert Özen 5 Tem 2026 11 dk 38 görüntülenme

İlk .NET 9 Web API projemizi kuruyoruz. Program.cs dosyasını satır satır açıyor, minimal hosting modelini, builder ile app ayrımını ve middleware sırasının neden önemli olduğunu anlıyoruz.

İlk Projeyi Kurmadan Önce: Neye İhtiyacın Var?

Koda geçmeden önce makinende iki şeyin olması yeterli: .NET 9 SDK ve bir editör. Editör tarafında Visual Studio, VS Code ya da JetBrains Rider fark etmez; ben örneklerde komut satırını kullanacağım, çünkü altında ne döndüğünü görmek istiyorum. SDK'nın yüklü olup olmadığını kontrol etmek için terminale şunu yaz:

dotnet --version

Eğer 9. ile başlayan bir sürüm numarası görüyorsan hazırsın. Görmüyorsan Microsoft'un resmi sitesinden .NET 9 SDK'yı indirip kurman gerekiyor. Bir not: SDK ile Runtime farklı şeyler. Runtime sadece çalıştırır, SDK ise geliştirme yapmanı sağlar. Bizim SDK'ya ihtiyacımız var.

Projeyi Oluşturmak

Şimdi boş bir klasör aç ve içine gir. Projemizi tek komutla oluşturuyoruz:

dotnet new webapi -n KullaniciApi

Burada webapi bir şablon adı. .NET'in içinde hazır gelen onlarca şablondan biri; API iskeletini bizim için kuruyor. -n ise projenin adını veriyor. Komutu çalıştırdığında KullaniciApi adında bir klasör oluşacak ve içi birkaç dosyayla dolacak. O klasöre girip projeyi çalıştıralım:

cd KullaniciApi
dotnet run

Terminalde birkaç satır log göreceksin ve bir de yerel adres, mesela http://localhost:5xxx gibi. İşte API'n ayakta. Henüz içinde kayda değer bir şey yok ama çalışıyor. Şimdi asıl önemli kısma, yani bu sihrin nerede döndüğüne bakalım.

1_eQjyva0NPFrFajInkZDfqQ.png

Program.cs: Her Şeyin Başladığı Yer

Projenin kök dizininde Program.cs adında bir dosya var. .NET 9 ile gelen webapi şablonunda bu dosya oldukça sade görünür. Aşağı yukarı şöyle bir şeyle karşılaşırsın:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddOpenApi();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

İlk bakışta az kod, ama her satırı bir iş yapıyor. Eskiden, .NET 5 ve öncesinde, bu işi iki ayrı dosya yapardı: Program.cs ve Startup.cs. Servis kayıtları bir yerde, middleware yapılandırması başka yerde dururdu. .NET 6 ile gelen minimal hosting modeli bu ikisini tek dosyada birleştirdi. Daha az dosya, daha az tören, konuya daha hızlı giriş. .NET 9'da da bu model devam ediyor.

Builder ve App: İki Ayrı Aşama

Bu dosyanın mantığını anladığında geri kalan her şey yerine oturuyor. Kod iki net aşamaya bölünmüş durumda. İlk aşama builder, ikincisi app. Aradaki dönüm noktası ise builder.Build() satırı.

builder.Build() çağrılana kadar olan kısım, uygulamanın nelere sahip olacağını tanımladığın yer. Buna hazırlık aşaması diyebiliriz. Burada servisleri kaydediyorsun: veritabanı bağlantısı, kimlik doğrulama, senin yazdığın sınıflar... Hepsi builder.Services üzerinden sisteme tanıtılıyor. Yukarıdaki örnekte AddControllers controller'ları, AddOpenApi ise API dokümantasyonu altyapısını kaydediyor.

builder.Build() satırından sonrası ise uygulamanın gelen isteklere nasıl davranacağını tanımladığın yer. Artık elimizde çalışmaya hazır bir app var ve ona "istek geldiğinde önce şunu yap, sonra bunu yap" diyoruz. Kısacası: builder tarafında neyin var olacağına, app tarafında ise bunların nasıl çalışacağına karar veriyorsun. Bu ayrımı bir kez oturttuğunda, ileride karşına çıkacak en karmaşık yapılandırmalarda bile kaybolmazsın.

Middleware Nedir ve Sıralaması Neden Bu Kadar Önemli?

App tarafındaki Use... ile başlayan satırlar middleware dediğimiz yapılardır. Middleware'i, gelen her isteğin geçmek zorunda olduğu bir dizi kapı gibi düşün. İstek kapıdan kapıya ilerler, her kapı isteğe bir şey yapar ya da yapmadan bir sonrakine geçirir.

Örneğin app.UseHttpsRedirection(), gelen isteği HTTPS'e yönlendiren bir kapı. app.UseAuthorization() ise "bu isteği yapan kişinin buna yetkisi var mı?" diye kontrol eden kapı. Buradaki kritik nokta şu: bu kapıların sırası, yazdığın satır sırasıyla belirlenir. Yani kod içinde önce yazdığın middleware, isteği önce görür.

Bu neden önemli? Küçük bir örnekle düşünelim. Diyelim ki yetkilendirme kontrolünü, isteğin kim tarafından yapıldığını belirleyen kimlik doğrulamadan önce koydun. O zaman yetkilendirme kapısı, daha ortada bir kullanıcı kimliği yokken "bu kişinin yetkisi var mı?" diye sormaya çalışır ve mantık çöker. Sıralama yanlış olduğunda hata mesajı bazen çok net olmaz; saatlerce neyin yanlış gittiğini ararsın. Bu yüzden middleware sırasını rastgele değil, bilinçli kur. İlerleyen yazılarda kendi middleware'imizi yazarken bu konuya çok daha derin gireceğiz.

app.Run() Ne Yapıyor?

Dosyanın en sonundaki app.Run(), uygulamayı başlatan ve onu ayakta tutan satırdır. Bu çağrı yapıldığı anda uygulama gelen istekleri dinlemeye başlar ve sen durdurana kadar çalışmaya devam eder. Yani programın akışı bu satırda "beklemeye" geçer. Bunu bir sunucunun açılış anahtarı gibi düşünebilirsin; çevirdiğin an motor çalışır ve sen kapatana dek durmaz.

Controller mı, Minimal API mı?

Yukarıdaki şablon controller tabanlı bir yapı kuruyor; yani endpoint'lerini ayrı sınıflarda tanımlıyorsun. Ama .NET'in bir de minimal API denen, endpoint'leri doğrudan Program.cs içinde tanımlamana izin veren daha hafif bir yaklaşımı var. Örneğin tek satırla bir endpoint yazabilirsin:

app.MapGet("/merhaba", () => "Selam dünya!");

Bu satırı app.Run()'dan önce ekleyip uygulamayı yeniden çalıştırırsan, tarayıcıdan /merhaba adresine gittiğinde "Selam dünya!" yazısıyla karşılaşırsın. İki yaklaşımın da yeri var ve hangisini ne zaman seçeceğini bir sonraki yazıda uzun uzun konuşacağız. Şimdilik bilmen gereken tek şey, ikisinin de aynı temel üzerine, yani bu Program.cs mantığı üzerine kurulu olduğu.

Özetlemeden Önce Denemeni İstediğim Şey

Bir sonraki yazıya geçmeden önce şunu dene: Yukarıdaki /merhaba endpoint'ini kendi projene ekle, çalıştır ve tarayıcıdan gör. Sonra da middleware satırlarının yerini bilinçli olarak değiştir, mesela app.UseAuthorization()'ı en üste al ve ne olduğunu gözlemle. Bir şeyi kırmak, onun neden o sırada durduğunu anlamanın en hızlı yoludur. Bir sonraki yazıda controller tabanlı yapı ile minimal API'yi karşılaştıracak, hangi projede hangisinin daha mantıklı olduğunu netleştireceğiz.