API Versioning — URL, header, query string versioning
Muammodan boshlaylik
Mahsulot javobida narx — oddiy raqam edi. Endi ko'p valyuta kerak:
// eski
{ "id": 5, "nomi": "Telefon", "narx": 3500000 }
// yangi
{ "id": 5, "nomi": "Telefon", "narx": { "summa": 3500000, "valyuta": "UZS" } }
O'zgarishni deploy qildingiz — 200 000 foydalanuvchidagi eski mobil ilova narx ni raqam deb o'qiydi va qulaydi. Ilovani App Store orqali yangilash — kunlar, ko'p foydalanuvchi esa umuman yangilamaydi.
Hayotiy o'xshatma
Elektr rozetkalar. Yangi standart chiqsa, eski rozetkalarni bir kunda sindirib tashlashmaydi — eski va yangi bir muddat yonma-yon ishlaydi, adapterlar sotiladi, va bir necha yildan keyin eskisi asta-sekin yo'qoladi. Hech kimning muzlatkichi bir kechada o'chib qolmaydi.
Qachon yangi versiya kerak
| Buzuvchi (breaking) — yangi versiya | Buzmaydigan — shu versiyada |
|---|---|
| Maydonni o'chirish yoki nomini o'zgartirish | Yangi ixtiyoriy maydon qo'shish |
| Maydon turini o'zgartirish | Yangi endpoint qo'shish |
| Majburiy so'rov parametri qo'shish | Yangi ixtiyoriy parametr |
| Status kodlar yoki xato formatini o'zgartirish | Ishlashni tezlashtirish |
| Endpoint ni o'chirish | Yangi enum qiymati (agar mijozlar noma'lumga tayyor bo'lsa) |
[!TIP] Eng yaxshi versiya — chiqarilmagan versiya. Ko'p o'zgarishlarni buzmasdan qilish mumkin: yangi maydonni qo'shing (
narxTafsilot), eskisini bir muddat qoldiring. Yangi versiya — haqiqatan buzuvchi o'zgarish uchun.
Versiyalash usullari
| Usul | Misol | Xususiyati |
|---|---|---|
| URL segment | /api/v2/mahsulotlar |
Eng aniq, brauzer va log da ko'rinadi, keng tarqalgan |
| Query string | /api/mahsulotlar?api-version=2.0 |
URL tuzilmasi o'zgarmaydi |
| Header | X-Api-Version: 2.0 |
URL toza; cache va brauzerda sinash qiyinroq |
| Media type | Accept: application/json;v=2 |
"REST-ga eng to'g'ri", amalda kam |
Asp.Versioning paketi
dotnet add package Asp.Versioning.Mvc
dotnet add package Asp.Versioning.Mvc.ApiExplorer
using Asp.Versioning;
builder.Services
.AddApiVersioning(o =>
{
o.DefaultApiVersion = new ApiVersion(1, 0);
o.AssumeDefaultVersionWhenUnspecified = true;
o.ReportApiVersions = true; // api-supported-versions sarlavhasi
o.ApiVersionReader = new UrlSegmentApiVersionReader();
})
.AddMvc()
.AddApiExplorer(o =>
{
o.GroupNameFormat = "'v'VVV";
o.SubstituteApiVersionInUrl = true;
});
Controller lar
[ApiController]
[ApiVersion(1.0, Deprecated = true)]
[Route("api/v{version:apiVersion}/mahsulotlar")]
public class MahsulotlarV1Controller(MahsulotService s) : ControllerBase
{
[HttpGet("{id:int}")]
public async Task<MahsulotV1Dto?> Ol(int id, CancellationToken ct) =>
(await s.OlAsync(id, ct))?.ToV1(); // eski format: narx — raqam
}
[ApiController]
[ApiVersion(2.0)]
[Route("api/v{version:apiVersion}/mahsulotlar")]
public class MahsulotlarV2Controller(MahsulotService s) : ControllerBase
{
[HttpGet("{id:int}")]
public async Task<MahsulotDto?> Ol(int id, CancellationToken ct) => await s.OlAsync(id, ct);
}
GET /api/v1/mahsulotlar/5 → { "narx": 3500000 }
GET /api/v2/mahsulotlar/5 → { "narx": { "summa": 3500000, "valyuta": "UZS" } }
Ikkala versiya — bitta servis va biznes mantiq; farq faqat DTO va mapping da.
Bitta controller da
[ApiVersion(1.0)]
[ApiVersion(2.0)]
[Route("api/v{version:apiVersion}/buyurtmalar")]
public class BuyurtmalarController : ControllerBase
{
[HttpGet]
public IActionResult Royxat() => ...; // ikkala versiyada
[HttpGet("statistika")]
[MapToApiVersion(2.0)]
public IActionResult Statistika() => ...; // faqat v2
}
Minimal API
dotnet add package Asp.Versioning.Http
var versiyalar = app.NewApiVersionSet()
.HasApiVersion(new ApiVersion(1, 0))
.HasApiVersion(new ApiVersion(2, 0))
.ReportApiVersions()
.Build();
var g = app.MapGroup("/api/v{version:apiVersion}/mahsulotlar").WithApiVersionSet(versiyalar);
g.MapGet("/{id:int}", OlV1).MapToApiVersion(1, 0);
g.MapGet("/{id:int}", OlV2).MapToApiVersion(2, 0);
Eski versiyani bekor qilish
Deprecated = true— javobdaapi-deprecated-versions: 1.0sarlavhasi- Hujjatda va mijozlarga e'lon: "v1 2027-yil 1-iyungacha ishlaydi"
- Log/metrikalarda v1 ishlatilishini kuzatish
- Muddat tugagach —
410 Goneyoki o'chirish
[!INFO] RFC 8594
Sunsetsarlavhasi (Sunset: Tue, 01 Jun 2027 00:00:00 GMT) — mijozlarga endpoint qachon o'chirilishini mashina o'qiy oladigan shaklda bildiradi. Asp.Versioning da sunset siyosatini sozlash mumkin.
Tez-tez uchraydigan xatolar
Har kichik o'zgarishga yangi versiya — v1...v9, hammasini qo'llab-quvvatlash imkonsiz.
Biznes mantiqni versiyalar bo'yicha nusxalash — xato bir versiyada tuzatilib, boshqasida qoladi; mantiq — bitta, faqat kontrakt (DTO) versiyalanadi.
Versiyasiz boshlash — keyin qo'shish og'riqli; birinchi kundan /api/v1/.
Xulosa
Versiyalash — buzuvchi o'zgarishlarni eski mijozlarni sindirmasdan chiqarish. Buzuvchi: maydonni o'chirish/turini o'zgartirish, majburiy parametr; qo'shish — buzmaydi. Usullar: URL segment (eng keng tarqalgan), query, header, media type.
Asp.Versioning: AddApiVersioning, [ApiVersion], v{version:apiVersion} route, MapToApiVersion; Minimal API da NewApiVersionSet. Biznes mantiq — bitta, versiyalanadi faqat DTO. Eskisini bosqichma-bosqich: Deprecated, e'lon, kuzatish, o'chirish.
Keyingi dars
74-dars: Health Checks — /health endpoint, baza holati