ASP.NET Core “ApiVersion Could Not Be Resolved” Hatası
Geçen ay bir finans kuruluşundaki müşterimiz beni aradı. “Aşkın bey, API’mize yeni endpoint’ler eklememiz lazım ama mevcut mobil uygulamayı bozamayız, ne yapalım?” dedi. Tanıdık geldi mi? Bence her API geliştiren ekip bu dertle en az bir kere uğraşıyor. Cevap kağıt üstünde basit: API versiyonlama. Ama işin pratiği var ya, hele OpenAPI dokümantasyonuyla düzgün yürütmeye kalkınca, olay biraz dağılıyor; en azından.NET 10 ve yeni Asp.Versioning v10 paketi çıkana kadar durum buydu.
📋 İçindekiler
-
dotnet add package Scalar.AspNetCore app.MapScalarApiReference(options => { options.WithOpenApiRoutePattern("/openapi/{documentName}.json"); });İkisini yan yana koyunca tablo daha net oluyor. Hani bazen uzun uzun anlatırsın da kafa karışır ya, burada öyle bir durum yok:
Özellik SwaggerUI Scalar Kurulum kolaylığı Orta Kolay Görsel tasarım Klasik, tanıdık Daha modern dürüyor Versiyon desteği Dropdown ile Otomatik keşif Topluluk desteği Çok geniş Büyüyor Özelleştirme Baya iyi gidiyor Daha esnek hissettiriyor Üretim ortamı kullanımı Tavsiye etmem, genelde kapatılır Tavsiye etmem, genelde kapatılır 💡 Bilgi: Production ortamında SwaggerUI veya Scalar’ı muhtemelen kapatın ya da authentication arkasına alın. Geçen yıl bir müşteride SwaggerUI açık kalmıştı, dışarıdan biri neredeyse tüm API yapısını görmüş; güvenlik denetiminde ortaya çıktı ve açık konuşayım, hiç hoş olmadı.
Tam da öyle.
Evet.Türkiye’deki Ekipler İçin Pratik Tavsiyeler
Araya gireyim: Şimdi asıl meseleye gelelim. Kaynaklarda hep “şunu yap, bunu yap” diye geçiyor ama Türkiye tarafında iş biraz başka akıyor, hani teoride güzel duran şeyler sahada bazen tökezliyor.
Birincisi, maliyet. Azure API Management kullanıyorsanız — versiyonlu API’leri toparlamak için baya iş gören bir araç bu — Developer tier bile aylık yaklaşık 50 USD civarında geziyor. TL’ye vurunca küçük ekip için hafif değil. Bütçe dar işe, önce Asp.Versioning ile başlayıp reverse proxy tarafında YARP ya da nginx kullanmak daha mantıklı olabilir; ama enterprise tarafta iş değişiyor, orada policy’ler, rate limiting ve analytics gerçekten ayrı bir rahatlık veriyor.
Bir dakika — bununla bitmedi.
İkincisi şu: Bizde sık gördüğüm hata, versiyonlama stratejisini netleştirmeden kod yazmaya başlamak. “Sonra bakarız” deniyor. Olmaz. Sonra çoğu zaman yetişmiyor. İlk günden karar verin; URL path mi olacak, header mı, semantic versioning mi yoksa date-based mi? Bu kararı ertelemek, teknik borcu sessizce büyütüyor, sonra da kimse niye bu kadar karmaşa çıktı diye anlamıyor.
Hani, Bir de.NET 10 tarafı var, burada iş biraz daha ilginç hâle geliyor. Built-in request validation geldiği için API versiyonlama daha da kritik oluyor. V1’de kurallar başka olabilir, v2’de yeni alanlar açılmış olabilir (ve evet, bu farkı sonradan kapatmak epey yoruyor). Her versiyonun kendi validation mantığı olmalı. Bunu Ubuntu 26.04’te.NET 10: Kurulum. Konteyner Rehberi yazımda.NET 10 kurulumu anlatırken de değinmiştim, orada yeni özelliklerin pratik etkisine biraz dokunmuştuk.
Şimdi gelelim işin can alıcı noktasına.
Evet.
Versiyonları Zamanla Nasıl Yönetirsiniz?
API versiyonu açmak kolay. Asıl uğraş, iş büyüyünce eski sürümleri kenara almak; yanı sessiz sedasız emekli etmek. Asp.Versioning burada da iş görüyor:
[ApiVersion("1.0", Deprecated = true)] public class ProductsController : ControllerBase { // v1 hâlâ çalışır ama "deprecated" olarak işaretlenir }Bunu ekleyince, OpenAPI dokümanında ve response header’larında (
api-deprecated-versions) bu bilgi otomatik görünür. İstemci de uyarıyı alır. Fena değil.Ama pratikte şunu gördüm, Türkiye’de eski versiyonları kapatmak bazen teknikten çok politik bir konu oluyor; “Ama X bankası hâlâ v1 kullanıyor, kapatamazsınız!” lafı dönüp dürüyor, sız de ortada kalıyorsunuz, o yüzden ben en baştan SLA içine versiyon ömrünü yazın diyorum (mesela “her versiyon GA’den itibaren 18 ay desteklenir” gibi), yoksa sonra iş uzuyor da uzuyor. Peki neden? Çünkü kural baştan yoksa, sonradan herkes kendi istediğini doğru sanıyor.
Ha bu arada, Azure DevOps Git Policy Yönetimi: 10x Hız Kazanmanın Yolu yazısında bahsettiğim branch policy’leri de versiyonlama stratejinizle aynı çizgide olmalı. Her majör versiyon için ayrı (söylemesi ayıp) bir release branch tutmak baya işe yarıyor; ben öyle yapınca ekip daha az karışıklık yaşıyor, ama tabi her projede birebir aynı sonucu vermez. Sız ne dersiniz?
Benim Karşılaştığım Sorunlar ve Çözümleri
Asp.Versioning v10’u ilk kurcaladığımda ufak ama can sıkıcı bir duvara tosladım. Minimal API route’larında
{version:apiVersion}constraint’i bir türlü tanınmıyordu; hata da netti:The constraint reference 'apiVersion' could not be resolved to a type. Peki neden? ÇünküAddApiVersioning‘den sonra.AddApiExplorer()çağrısını da eklemek gerekiyormuş, ben işe sadece ilk kısmı koyup explorer tarafını atlamışım; işte o küçük eksik yüzünden iki saat gitti, baya sınır bozucuydu.Bir de OpenAPI tarafında versiyon parametresinin
required: truediye görünmesi var. İlk bakışta “tamam, normal” diyorsunuz, ama sonra NSwag ya da AutoRest gibi istemci üreten araçlar her istekte bu versiyonu zorunlu tutmaya başlayınca iş biraz değişiyor. Bazı ekipler bunu ister, bazıları istemez; yanı durum biraz gri.AssumeDefaultVersionWhenUnspecifiedayarı burada rahatlatıyor, fakat dokümanın içinde parametre yine zorunlu görünüyor. Şey, %100 doğru olmayabilir ama sanırım bir transformer yazıp OpenAPI çıktısında o required bayrağını kaldırmak mümkün.Evet.
Açık konuşayım, özellik fena değil. Ama bazı edge case’lerde hâlâ toparlanması gerekiyor gibi dürüyor; hani insan kullanırken “tam oturdu” demiyor. Neyse uzatmayayım, zamanla daha da oturur diye düşünüyorum.
İlk Adım Olarak Ne Yapmalısınız?
Eğer elinizde hali hazırda bir.NET proje varsa. Buna versiyonlama eklemek istiyorsanız, işin başında biraz durup nefes alın. Sonra planı netleştirin:
- Önce versiyonlama stratejinizi belirleyin (ben URL path tarafını daha pratik buluyorum)
- Asp.Versioning v10 paketlerini ekleyin
- Mevcut endpoint’lerinizi v1 olarak etiketleyin — hiçbir şeyi kırmadan ilerleyin
- OpenAPI entegrasyonunu kurun, her versiyon için ayrı doküman üretin
- SwaggerUI veya Scalar ekleyin (development ortamı için yeterli oluyor)
- Yeni değişiklikler için v2 oluşturmaya başlayın
- CI/CD pipeline’ınızda her versiyon için ayrı test suite’leri çalıştırın
İlk üç adımı, açık konuşayım, bir günde toparlayabilirsiniz. Ciddi..NET 10 ile Asp.Versioning v10 bu işi baya kolaylaştırmış; ben denediğimde resmen “keşke bu iki yıl önce gelseydi” dedim, çünkü uğraştıran kısımların çoğu artık daha derli toplu ilerliyor ve insanın kafası da biraz rahat ediyor. .NET 10 Data Protection Güvenlik Açığı. Acil Yama yazısında da.NET 10 ekosistemine dair önemli notlar paylaşmıştım, göz atmanızı tavsiye ederim.
“The constraint reference ‘ApiVersion’ could not be resolved to a type” hatası nasıl çözülür?
Bu hata neredeyse her zaman tek bir nedenden çıkar: route şablonunuzda URL path versioning kullanıyorsunuz (örneğin
api/v{version:apiVersion}/[controller]) amaapiVersionroute constraint’i hiçbir zaman kayıt edilmemiş. ASP.NET Core, route tablosunu kurarken{version:apiVersion}token’ını bir tipe çözemediği içinInvalidOperationExceptionfırlatır.En sık karşılaşılan tetikleyici,
AddApiVersioning()çağrılırken.AddMvc()uzantısının unutulmasıdır. Controller tabanlı projedeapiVersionconstraint’iniConstraintMap‘e ekleyen tam olarak bu çağrıdır. İkinci sık neden de yanlış paket:Asp.Versioning.Httptek başına MVC route constraint’lerini kaydetmez — controller projesindeAsp.Versioning.Mvcpaketi gerekir.Doğru kayıt şu şekilde —
.AddMvc()satırı kritik:builder.Services.AddApiVersioning(options => { options.DefaultApiVersion = new ApiVersion(1, 0); options.AssumeDefaultVersionWhenUnspecified = true; options.ReportApiVersions = true; }) .AddMvc() // controller route constraint'ini ConstraintMap'e ekler .AddApiExplorer(options => { options.GroupNameFormat = "'v'VVV"; options.SubstituteApiVersionInUrl = true; });Constraint’i elle kaydetmeniz gereken kenar durumlarda ise doğrudan
RouteOptionsüzerinden ekleyebilirsiniz:builder.Services.Configure(options => { options.ConstraintMap.Add("apiVersion", typeof(ApiVersionRouteConstraint)); }); Framework yükseltmesinden sonra bu hata neden ortaya çıkıyor?
Çünkü yükseltme sırasında versiyonlama kayıt API’si değişmiş ve
.AddMvc()ya da MVC paketi eski yapılandırmada düşmüş olabilir. EskiMicrosoft.AspNetCore.Mvc.Versioning‘den yeniAsp.Versioning.*paketlerine geçerken bu özellikle sık görülür. Çözüm:Asp.Versioning.MvcveAsp.Versioning.Mvc.ApiExplorerpaketlerinin yüklü olduğundan emin olun veAddApiVersioning()zincirinde.AddMvc()çağrısının yer aldığını doğrulayın.Sıkça Sorulan Sorular
API versiyonlama için ne yapmalıyım?
Çoğu proje için URL path versioning (yanı
/api/v1/resourcegibi bir yapı) en pratik seçenek. Anlaması ve debug etmesi çok kolay, açıkçası bence de en temiz yol bu (ben de ilk duyduğumda şaşırmıştım). Enterprise ortamda API gateway kullanıyorsanız header versioning da fena bir alternatif değil. Ama hangisini seçerseniz seçin — projenin başında karar verin ve o çizgide kalın.Peki neden?
.NET 10 olmadan Asp.Versioning v10 çalışır mı?
Hayır, çalışmıyor. Asp.Versioning v10 paketi.NET 10 target framework’ünü gerektiriyor..NET 8 veya.NET 9 kullanıyorsanız, Asp.Versioning’in önceki sürümlerini (v8 veya v9) kullanmanız gerekiyor. Tecrübeme göre, built-in OpenAPI entegrasyonunun bu kadar temiz çalışmasını istiyorsanız.NET 10’a geçmeye değer.
Eski API versiyonlarını ne zaman kapatayım?
Açıkçası, Aslında en mantıklısı, her versiyonun ömrünü en baştan belirlemek. Genelde GA tarihinden itibaren 12-18 ay destek verip, önce “deprecated” olarak işaretlemek, ardından 3-6 aylık bir grace period tanıyıp kapatmak işe yarıyor. İstemcilerinize yeterli süre tanıyın, ama süresiz destek vaat etmeyin — bence bu kısmı çoğu ekip atlıyor.
Minimal API mi kullansam, Controller mı?
Küçük ve orta ölçekli projelerde Minimal API yeterli, hem daha az boilerplate kodu oluyor. Büyük kurumsal projelerde işe, özellikle karmaşık iş mantığı olan yerlerde, controller’lar çok daha organize bir yapı sunuyor. Mesela ikisini aynı projede birlikte de kullanabilirsiniz — Asp.Versioning bunu zaten destekliyor.
OpenAPI dokümanlarını production’da açık bırakayım mı?
Bence kapatın ya da authentication arkasına alın. OpenAPI dokümanları hani tüm API yapınızı, endpoint’lerinizi ve veri modellerinizi dışarıya açıyor. Development. Staging ortamlarında açık bırakabilirsiniz, ama production’da ya tamamen kapatın ya da sadece yetkili kullanıcılara açın. Açıkçası bu konuda ödün vermeyin.
Çok konuştum, örnekle göstereyim.
Kaynaklar ve İleri Okuma
Bence, API Versioning in.NET 10 Applications —.NET Blog
Araya gireyim: ASP.NET API Versioning — GitHub Repository
Ayşe T.
Tam zamanında bir yazı olmuş, biz de şu aralar mevcut bir API’yi versiyonlamaya çalışıyoruz ve OpenAPI tarafında epey sancı çekiyoruz. Swagger yerine Scalar’ı hiç denemedim, bir bakacağım. Bu arada tamamen farklı bir konu ama şu yazınız da güzeldi: SPFx Yol Haritası Nisan 2026: AI Özellikleri ve 1.23 RC — https://www.askinkilic.com.tr/spfx-yol-haritasi-nisan-2026-ai-ozellikleri-ve-123-rc/
Pınar H.
Tam zamanında bir yazı, geçen ay legacy bir API’yi versiyonlamaya çalışırken epey saçımı yoldurmuştum. OpenAPI entegrasyonu kısmını özellikle merak ediyorum, Scalar ile SwaggerUI arasındaki farkı pratikte nasıl hissediyorsunuz? Bu arada şu yazınız da güzeldi: VS Code Python Environments Nisan Güncellemesi: Hız Farkı — https://www.askinkilic.com.tr/vs-code-python-environments-nisan-guncellemesi-hiz-farki/
Yorumlar kapalı.







2 comments