Sem Göksu
Sem Göksu
Yazılım · Yolculuk · Fenerbahçe
.NET Core API

.NET Core API — Bölüm 3: Swagger ile API Dokümantasyonu

Serinin son durağı: API'mizi Swagger/OpenAPI ile dokümante ediyoruz. XML comments, DTO pattern, JWT auth entegrasyonu, API versioning ve modern alternatif Scalar — profesyonel API dokümantasyonunun her yönü.

23 Nisan 2026 6 dk okuma 17 0
Swagger UI - /swagger/index.html uzerinden API endpoint'leri, JWT icin Authorize butonu acik.
Swagger UI - /swagger/index.html uzerinden API endpoint'leri, JWT icin Authorize butonu acik.

IDE tarafinda: Tarayici tarafinda /swagger/index.html'e gittiginizde otomatik uretilmis OpenAPI dokumantasyonu karsinizda. Authorize butonuna JWT token'i yapistirip korumali endpoint'leri direkt UI uzerinden deneyebilirsiniz.

Merhaba arkadaşlar, .NET Core API serisinin son bölümünde API'mizi hem geliştiriciler hem de kendi ekibimiz için dokümante etmek konusunu inceliyoruz. Kötü dokümante edilmiş bir API ne kadar güçlü olursa olsun kimse kullanmaz. İyi haber: Swagger/OpenAPI ile bu işi neredeyse sıfır efor ile yapabiliyoruz. Üstelik "Try it out" butonu sayesinde canlı deneme bile yapılabiliyor.

OpenAPI mı, Swagger mı? Terminoloji
Önce terimleri netleştirelim — yıllar içinde karıştığını çok gördüm:

- OpenAPI Specification (OAS): API'nizi tanımlayan standart bir JSON/YAML formatı. "Bu API'de şu endpoint var, şu parametreyi alır, şu response döner" diye anlatır.
- Swagger: OpenAPI'yi kullanan ve görselleştiren araçlar ailesi. Swagger UI en bilineni — OpenAPI dokümanından interaktif bir web arayüzü üretir.
- Swashbuckle: .NET için Swagger araçlarını entegre eden NuGet paketi. Aslında biz bunu kullanıyoruz.

Yani biz OpenAPI dokümanı üretiyoruz, Swagger UI bunu görselleştiriyor. .NET 9 ile gelen yerleşik OpenAPI desteği sayesinde Swashbuckle'a bile ihtiyaç kalmadı bazı senaryolarda.

.NET 9 ile Yerleşik OpenAPI
dotnet new webapi ile oluşturulan projede Swagger otomatik gelir, hatta .NET 9 ile birlikte Microsoft.AspNetCore.OpenApi paketi yerleşik olarak spec üretiyor. Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddOpenApi(); // ← .NET 9 yerleşik

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi(); // /openapi/v1.json endpoint'i
}

app.MapControllers();
app.Run();
Bu kadar basit. Artık /openapi/v1.json adresinde API'nizin tam OpenAPI 3.x spec'i hazır.

Swagger UI'yi Entegre Edelim
Yerleşik OpenAPI JSON üretiyor ama görsel arayüz için ya Swagger UI ya da yeni bir alternatif olan Scalar kullanıyoruz. İkisini de göstereyim:

// Swagger UI için
dotnet add package Swashbuckle.AspNetCore

// Scalar için (.NET 9 ile popüler, daha şık görünüm)
dotnet add package Scalar.AspNetCore
Program.cs'te:

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
    {
        Title = "SemGoksu API",
        Version = "v1",
        Description = "Sem Göksu blog'un API dokümantasyonu",
        Contact = new() { Name = "Sem Göksu", Email = "admin@semgoksu.com", Url = new Uri("https://semgoksu.com") }
    });
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "SemGoksu API v1");
        c.RoutePrefix = "swagger"; // /swagger adresinde gösterir
    });
}
Uygulamayı çalıştırıp https://localhost:7000/swagger adresine gittiğinizde karşınıza çıkacak UI tüm endpoint'leri gruplara ayırır, her biri için request/response şemasını gösterir, "Try it out" ile anında deneme yapabilirsiniz.

Endpoint'leri Belgelendirelim
Varsayılan dokümantasyon iyi ama ilave açıklama, parametre detayı, örnek response eklemek çok değerli. Bunun için XML doc comment'leri kullanıyoruz. Önce .csproj'a:

<PropertyGroup>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
  <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
Program.cs'te AddSwaggerGen'i güncelleyelim:

builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new() { Title = "SemGoksu API", Version = "v1" });

    // XML dokümanlarını dahil et
    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    if (File.Exists(xmlPath))
        c.IncludeXmlComments(xmlPath);
});
Artık controller metodlarımıza /// ile anlamlı doküman yazabiliriz:

/// <summary>
/// Belirli bir yazıyı ID ile getirir.
/// </summary>
/// <param name="id">Yazının benzersiz ID değeri</param>
/// <returns>Yazı detayı</returns>
/// <response code="200">Yazı bulundu ve döndürüldü</response>
/// <response code="404">Belirtilen ID ile yazı bulunamadı</response>
[HttpGet("{id:int}")]
[ProducesResponseType(typeof(Yazi), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> Getir(int id)
{
    var yazi = await servis.GetirAsync(id);
    return yazi is null ? NotFound() : Ok(yazi);
}
[ProducesResponseType] attribute'ları sayesinde Swagger UI hangi status code'larda ne dönebileceğinizi biliyor ve güzel şemalar üretiyor.

JWT Authentication'ı Swagger'a Tanıtalım
Önceki bölümde eklediğimiz JWT auth'unu Swagger UI'da da kullanabilmek için entegre edelim ki "Try it out" yaparken token gönderebilelim:

builder.Services.AddSwaggerGen(c =>
{
    // ... mevcut ayarlar

    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Name = "Authorization",
        Type = SecuritySchemeType.Http,
        Scheme = "Bearer",
        BearerFormat = "JWT",
        In = ParameterLocation.Header,
        Description = "JWT Authorization header. Değer: Bearer {token}"
    });

    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            },
            Array.Empty<string>()
        }
    });
});
Artık Swagger UI'da sağ üstte Authorize butonu çıkacak. Tıkladığınızda token'ı bir kez girip tüm endpoint'lerde kullanabilirsiniz.

DTO'larla Response'ları Zenginleştirelim
Dokümantasyon kadar önemli bir konu — API'lerinizde entity'leri direkt döndürmek yerine DTO (Data Transfer Object) kullanın:

// DTO — sadece dışarı açmak istediğimiz alanlar
public record YaziDto(int Id, string Baslik, string Icerik, DateTime Tarih);
public record YaziCreateDto(string Baslik, string Icerik);
public record YaziUpdateDto(string Baslik, string Icerik);

[HttpGet("{id:int}")]
[ProducesResponseType(typeof(YaziDto), 200)]
public async Task<ActionResult<YaziDto>> Getir(int id)
{
    var yazi = await servis.GetirAsync(id);
    if (yazi is null) return NotFound();
    return Ok(new YaziDto(yazi.Id, yazi.Baslik, yazi.Icerik, yazi.Tarih));
}
Bu yaklaşımın avantajları:

- Güvenlik: DB entity'sindeki hassas alanları (örn. SifreHash) dışarı sızdırmazsınız.
- Versiyonlama: DTO değişmeden entity değişebilir.
- Net dokümantasyon: Swagger sadece doğru alanları gösterir.
- Azaltılmış payload: İstemcinin ihtiyacı olmayan alanlar gönderilmez.

Entity → DTO mapping için Mapster veya AutoMapper kullanabilirsiniz ama C# 12+ record syntax'ı ile elle de çok rahat.

API Versiyonlama
Production'da API'niz yaşadıkça değişir ama eski istemcileri kırmayın. Versiyonlama için Asp.Versioning.Mvc.ApiExplorer:

dotnet add package Asp.Versioning.Mvc.ApiExplorer
builder.Services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ReportApiVersions = true;
    options.ApiVersionReader = new UrlSegmentApiVersionReader();
})
.AddApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VVV";
    options.SubstituteApiVersionInUrl = true;
});
Controller'da:

[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
[ApiVersion("2.0")]
public class YazilarController : ControllerBase
{
    [MapToApiVersion("1.0")]
    [HttpGet]
    public IActionResult TumuV1() => Ok(/* eski format */);

    [MapToApiVersion("2.0")]
    [HttpGet]
    public IActionResult TumuV2() => Ok(/* yeni format */);
}
URL'ler: /api/v1/yazilar ve /api/v2/yazilar. Swagger otomatik iki ayrı dokümantasyon üretir.

Production'da Swagger — Açık mı Kapalı mı?
Klasik tartışma. Benim pratik tavsiyem:

- Public API (başkaları kullanıyor) → Evet, açık bırakın. Kullanıcıların buna ihtiyacı var.
- Internal API (sadece kendi uygulamanız kullanıyor) → Kapatın ya da auth'un arkasına alın. Saldırı yüzeyini azaltır.
- Hibrit: Staging/production'da Swagger'ı kapatın ama pipeline'da /openapi/v1.json'u bir dosya olarak yayımlayın, ekibinizin erişebileceği bir developer portalında (Scalar, Redoc vs.) gösterin.

// Production'da kapalı
if (app.Environment.IsDevelopment() || app.Configuration.GetValue<bool>("EnableSwagger"))
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
Scalar — Daha Modern Alternatif
Swagger UI biraz eskice görünüyor. Scalar çok daha modern bir arayüz sunuyor ve kurulumu kolay:

builder.Services.AddOpenApi(); // .NET 9 yerleşik

// ... app build
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
    app.MapScalarApiReference(); // /scalar/v1 adresinde
}
Hem dark mode, hem gerçek kod örnekleri (curl, Python, C# gibi), hem de daha hızlı. Yeni projelerde denemenizi tavsiye ederim.

Tüm Seriyi Özetleyelim
Üç bölümlük bu serinin sonuna geldik. Şimdi elimizde:

- Bölüm 1: RESTful API temelleri — Controller + Minimal API, DI, HTTP verbs, validation
- Bölüm 2: JWT ile authentication, rol tabanlı yetkilendirme, current user erişimi
- Bölüm 3: OpenAPI/Swagger ile dokümantasyon, DTO pattern, API versioning

Bu üç yapı taşıyla profesyonel seviyede bir .NET Core API yazabilirsiniz. Gerisi ayrıntı: logging, EF Core ile DB, caching, rate limiting, CI/CD — her biri için ayrı makale yazacağız.

Sonraki adımlar
İleri konularla devam etmek isterseniz şunlara bakabilirsiniz:

- Entity Framework Core ile veritabanı entegrasyonu
- Serilog ile yapılandırılmış loglama
- Health checks ve readiness probe'lar
- Rate limiting (.NET 7+ yerleşik)
- Output caching ve response compression
- gRPC ile yüksek performanslı service-to-service iletişim
- Docker ile containerize etme ve Kubernetes'e deploy

Seriyi takip ettiğiniz için teşekkürler, yorumlarda ne tür konular görmek istediğinizi belirtin. Sağlıcakla kalın, başka bir makalede görüşmek üzere...
Paylaş:

Yorumlar (0)

Henüz yorum yok. İlk yorumu sen yap!

Yorum bırak

* Yorumlar moderasyon sonrası yayınlanır. E-posta gizli tutulur.