Merhaba ,
A : Arkadaşlar API de değişiklik mi oldu ?
B : Evet , Bazı değişiklikler yaptık.
A : Madde üzerinde değişiklik yorumunu göremiyorum ?
*******************
A : Save Post Methoduna hangi parametreleri göndermem gerekiyor , dönüş yapar mısın ?
B : İlk fırsatta dönüş yapıyorum.. ( Toplantı , acil problemler ) 4 Saat Sonra..
B : Parametreleri gönderdim..
********************
A : API yanlış sonuç dönüyor kontrol eder misin ?
B : Hangi parametreleri gönderiyorusun ?
– 3 saat sonra
B : ?????
Yukarıda gün içinde sıklıkla duyduğunuz cümleler varsa bir şeyler ters gidiyordur.
Ekipler aynı ofisde hatta yan yana bile çalışsa bu tarz senkron bozuklukları her zaman olabiliyor.
Özetlemek gerekirse bir problemin tanımına ulaşmak veya argümanlarıyla birlikte problemi tanımlamak teknik anlamda çözümlenmesinden çok daha fazla zaman alıyor..
Bu makalemizde API methotlarının dokümantasyon ve test süreçlerinin iyileştirilmesi adına AspNet Core 3.0 üzerinde API ( dökümantasyon ve test süreçlerinin yönetilebilir olması açısından ) Swagger implementasyonunu inceleyeceğiz.
Swagger Nedir ?
Basit anlamda API servislerimizin dökümantasyonunun çıkartılması ve kolaylıkla response alınmasını sağlayan bir araçtır. Microsoft’un API projelerinde kısmı dökümantasyon çıkaran Help sayfasının yanısıra API Methotlarının gösterim şekli , uygulanabilirliği , test edilebilir olması ve dökümantasyon işini dinamik bir şekilde özetleyebilmesi açısından oldukça ön plana çıkmıştır.
Swagger API endpoint adreslemesini dinamik bir şekilde yapmaktadır. Aslında özünde json formatında API method bilgiler içermektedir. Methodun alacağı parametreler , tipleri , default geri dönüş tipi , endpoint url bilgisi kısacası tüm schema bilgisini saklamaktadır.
Aşağıda kullanacağımız uygulamanın swagger.json schema bilgilerine ulaşabilirsiniz..
https://localhost:44380/swagger/v1/swagger.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
{ "openapi": "3.0.1", "info": { "title": "WeatherForecastAPI", "version": "v1" }, "paths": { "/api/WeatherForecast/Get": { "get": { "tags": [ "WeatherForecast" ], "responses": { "200": { "description": "Success" } } } }, "/api/WeatherForecast/Save": { "post": { "tags": [ "WeatherForecast" ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WeatherForecast" } }, "text/json": { "schema": { "$ref": "#/components/schemas/WeatherForecast" } }, "application/*+json": { "schema": { "$ref": "#/components/schemas/WeatherForecast" } } } }, "responses": { "200": { "description": "Success" } } } } }, "components": { "schemas": { "WeatherForecast": { "type": "object", "properties": { "date": { "type": "string", "format": "date-time" }, "temperatureC": { "type": "integer", "format": "int32" }, "temperatureF": { "type": "integer", "format": "int32", "readOnly": true }, "summary": { "type": "string", "nullable": true } }, "additionalProperties": false } } } } |
Başlayalım
.NetCore 3.0 üzerinde Template API ile bir proje oluşturalım.
Projemize NugetPackageManager üzerinden Swashbuckle.AspNetCore Nuget’i yükleyelim.
SwaggerConfiguration
Sırasıyla Swagger Configürasyonu için gerekli kodları yazalım.
appsettings.json
Swagger için Route, Title ve EndPoint değerlerimizi config üzerinde parametrik olarak belirleyelim.
1 2 3 4 5 6 7 8 9 10 |
"SwaggerOpt": { "Route": "swagger/{documentName}/swagger.json", "Title": "API Swagger", "EndPoint": "v1/swagger.json" }, ..... |
Startup.cs
Startup.cs sınıfı içerisinde ConfigureServices ve Configure methotlarında birkaç kural belirleyeceğiz.
Öncelikle appsetting.json üzerinde SwaggerOpt key ile tanımladığım parametreleri model üzerine Bind işlemini gerçekleştirelim.
SwaggerOpt ismiyle bir sınıf oluşturalım.
1 2 3 4 5 6 7 8 9 10 |
public class SwaggerOpt { public string Route { get; set; } public string Title { get; set; } public string EndPoint { get; set; } } |
Configure methodu içerisinde;
GetSection ile config üzerinden swagger parametrelerini okuyacağız Bind ile swagger için oluşturduğumuz sınıfa aktaracağız.
Bind işlemi için swaggerOpt sınıfı değişkenleri appsetting.json üzerine tanımlanan parametrelerle aynı olmalıdır.
1 2 3 4 5 6 |
SwaggerOpt _opt = new SwaggerOpt(); Configuration.GetSection("SwaggerOpt").Bind(_opt); |
Uygulamamızı swagger’dan haberdar etmemiz gerekiyor. app.UseSwagger ve UseSwaggerUI bildirimlerini aşağıdaki gibi gerçekleştirebilirsiniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
app.UseSwagger(op => { op.RouteTemplate = _opt.Route; }); app.UseSwaggerUI(op => { op.SwaggerEndpoint(_opt.EndPoint, _opt.Title); }); |
ConfigureServices metodu içerisinde;
1 2 3 4 5 6 7 8 9 10 11 12 |
services.AddSwaggerGen(opt => { opt.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "WeatherForecastAPI", Version = "v1" }); }); |
Swagger için gerekli configurasyonlar tamamlandı, Şimdi Dummy Datayı generic bir yapıda implement edelim.
WeatherForecast Model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class WeatherForecast { public DateTime Date { get; set; } public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string Summary { get; set; } } |
Generic IDummy<T> Data interface
1 2 3 4 5 6 7 8 |
public interface IDummyData<T> where T : class { public IList<T> Data { get; set; } } |
WeatherForecastData sınıfımız
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public class WeatherForecastData : IDummyData<WeatherForecast> { public WeatherForecastData() { FillData(); } private void FillData() { WeatherForecast = new List<WeatherForecast> { new WeatherForecast { Date = new DateTime(2019, 10, 14), Summary = "Hot", TemperatureC = 26 }, new WeatherForecast { Date = new DateTime(2019, 10, 15), Summary = "Hot", TemperatureC = 27 }, new WeatherForecast { Date = new DateTime(2019, 10, 16), Summary = "Sweltering", TemperatureC = 32 }, new WeatherForecast { Date = new DateTime(2019, 10, 17), Summary = "Cool", TemperatureC = 14 }, new WeatherForecast { Date = new DateTime(2019, 10, 18), Summary = "Cool", TemperatureC = 10 }, new WeatherForecast { Date = new DateTime(2019, 10, 19), Summary = "Balmy", TemperatureC = 20 }, new WeatherForecast { Date = new DateTime(2019, 10, 20), Summary = "Balmy", TemperatureC = 20 } }; } private static IList<WeatherForecast> WeatherForecast { get; set; } public IList<WeatherForecast> Data { get => WeatherForecast; set => WeatherForecast = value; } } |
Tekrar startup.cs ‘e dönüp ConfigureServices metodu üzerinde oluşturduğumuz WeatherForecastData sınıfımızı Singleton ayaklandıralım.
1 2 3 4 5 |
services.AddSingleton<IDummyData<WeatherForecast>, WeatherForecastData>(); |
Son adım olarak API Controller da methodlarımızı ekleyelim.
api/ControllerName/Method name şeklinde route belirledim.
api/WeatherForecast/Get
api/WeatherForecast/Post
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
[ApiController] [Route("api/[controller]")] public class WeatherForecastController : ControllerBase { private readonly IDummyData<WeatherForecast> _weatherForecastData; public WeatherForecastController(IDummyData<WeatherForecast> weatherForcastData) { _weatherForecastData = weatherForcastData; } [HttpGet] [Route("Get")] public IActionResult Get() { return Ok(_weatherForecastData.Data); } [HttpPost("Save")] public IActionResult Add([FromBody] WeatherForecast forecast) { _weatherForecastData.Data.Add(forecast); return Ok(new { Success = true }); } } |
Startup.cs içerisine eklediğimiz kodların son halini bütün şekişlde burada görebilirsiniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddSingleton<IDummyData<WeatherForecast>, WeatherForecastData>(); services.AddSwaggerGen(opt => { opt.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "WeatherForecastAPI", Version = "v1" }); }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); SwaggerOpt _opt = new SwaggerOpt(); Configuration.GetSection("SwaggerOpt").Bind(_opt); app.UseSwagger(op => { op.RouteTemplate = _opt.Route; }); app.UseSwaggerUI(op => { op.SwaggerEndpoint(_opt.EndPoint, _opt.Title); }); } } |
Projeyi ayaklandırıp , localhost üzerinden swagger ‘ı tetikleyebilirsiniz..
https://localhost:44380/swagger/index.html
Artık projemizde API dökümantasyonumuz mevcut. Makalemizin başında yazdığımız problemlerin çözümün için Swagger !
Get
Post