Merhaba, bugün sizlere bir süredir yazmayı istediğim .Net 6 ve Minimal Api den bahsetmeye çalışacağım. Daha sonrada Minimal api ile get,post,put ve delete işlemleri gerçekleştirdiğimiz, swaggerı eklediğimiz bir örnek yaparak, bazı yeniliklerden bahsedeceğim.
.Net 6
Öncelikle .Net 6 ile konumuza başlayalım. Microsoft’un “The fastest .Net” sloganıyla duyurduğu framework performans açısından gerçekten iyi sonuçlar veriyor. (Detay merak edenler için ilgili linki sayfanın altında paylaştım). Ayrıca .Net 6 LTS(Long Term Support) sürüm olarak çıktı. Yani kısaca Microsoft bu sürüme uzun süreli destek verecek (3 yıl) ve managementını sağlayacak. Bundan önceki en son LTS sürüm NET Core 3.1 di.


Sol taraf .Net 5, Sağ taraf .Net 6
.Net 6 içerisinde bir çok yeni özellik barındırıyor. Bu yeniliklerin detayını bulabileceğiniz Microsoft linkini yazının altına ekledim. Oradan detaylı olarak inceleyebilirsiniz fakat ben yine de yeni özelliklerden bazılarının konu başlıklarını aşağıda maddeler halinde belirteyim. Biz bugün biraz daha minimal api ve .Net 6 yapısı üzerine yoğunlaşacağız.
-
C# 10
-
F# 6
-
.Net MAUI(.Net Multi Platform App UI)
-
Minimal APIs
-
Entity framework Core geliştirmeleri
-
Hot Reload (Uygulama çalışırken yeni bir değişikliği görüntülemeyi sağlar.)
-
HTTP/3
-
System.Text.Json geliştirmeleri(Source Generators. Streamable Serialize/Deserialize, IgnoreCycles)
-
System.linq geliştirmeleri
-
ModuleInitializer Attribute (İlk çalıştırılacak metodu belirtmek için kullanılır)
- PriorityQueue (Queue yapılarına öncelik verilerek buna göre işlem yapılmasını sağlar)
Baştan söyleyeyim minimal apileri kullanmak zorunda değilsiniz eski tarz controller üzerinden de geliştirmeler yapılabilmektedir. Hatta “webapi” template içerisinde yine controllerlı yapı default olarak gelmektedir. İlk olarak boş bir Asp .Net Core projesi oluşturalım ve Net 6 yı seçelim. Vs code kullanacaksanız “dotnet new web”
İlk gözümüze çarpan Startup.cs olmaması olacaktır. Evet artık Startupda yaptığımız servis, middlewware konfigursayonlarımızı artık direk Program.cs içerisinde yapacağız.
Program.cs içerisini açtığımızda bizi gayet sade bir sayfa karşılıyor. (Burada syntax biraz Go ve Pythona benzemiş.)

Farkettiğiniz gibi main metodumuz yok. Net 6 default olarak Top level statement özelliği ile gelmektedir. Yani program.cs içeriisnde yazdığımız kodlar direk main metodu içerisinde yazılmış gibi düşünebilirsiniz. Yine bununla beraber usingler global olarak ekleniyor, bu özellik csproj dosyasında implicityusing flagi ile kontrol edilebilir.
Builder nesnemizi kullanarak tanımlamaları yapacağız. Artık eskiden default olarak gelen 5000 ve 5001 portları değişmiş. Yine port ayarları launchsettings içerisinde hem de app.Urls kullanarak program.cs içerisinde tanımlanabiliyor.
Güzel özelliklerden biride program.cs içerisinde ConfigureManager ile yeni config dosyalarını uygulamamızın içerisine eklememizin çok daha kolay ve maliyetsiz olması.
ConfigurationManager configurationManager = new(); configurationManager.AddJsonFile("config.json"); var value = configurationManager["Key"];
Şimdi ben bir servis tanımlayarak burada dummy datalar ile crud operasyonları gerçekleştireceğim. Bu servisi singleton olarak (Dummy datalar kaybolmasın tek instance çalışsın istediğim için) register ederek operasyonlarımda kullanacağım. Bununla beraber swaggerı apime ekleyeceğim ve bunların hepsini (servisin sınıfı hariç) sadece program.cs içerisinde yapacağım .
public class Jersey { public int Id { get; set; } public Player Player { get; set; } } public class Player { public int Id { get; set; } public string Name { get; set; } }
public interface IJerseyService { List<Jersey> GetAll(); Jersey Get(int id); int Insert(Jersey jersey); Jersey Update(int id, string playerName); bool Delete(int id); } public class JerseyService : IJerseyService { public List<Jersey> Jerseys { get; set; } public JerseyService() { Jerseys = new List<Jersey> { new Jersey{ Id = 12, Player = new Player{ Id = 30, Name = "Ersin Destanoglu" } }, new Jersey{ Id = 3, Player = new Player{ Id = 2, Name = "Ridvan Yilmaz" } }, new Jersey{ Id = 15, Player = new Player{ Id = 3, Name = "Miralem Pjanic" } } }; } public List<Jersey> GetAll() => Jerseys; public Jersey Get(int id) => Jerseys.Find(x => x.Id == id); public int Insert(Jersey jersey) { Jerseys.Add(jersey); var insertedJersey = Get(jersey.Id); return insertedJersey != null ? insertedJersey.Id : 0; } public Jersey Update(int id, string playerName) { var jersey = Get(id); if (jersey == null) return null; jersey.Player.Name = playerName; return jersey; } public bool Delete(int id) { var jersey = Get(id); if (jersey == null) return false; return Jerseys.Remove(jersey); } }
Swagger eklemek için Swashbuckle.AspNetCore paketini yükleyelim
install-package Swashbuckle.AspNetCore //dotnet add package Swashbuckle.AspNetCore
builder nesnemizi kullanarak swaggerın kullanacağı servisleri inject edelim.
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen();
Şimdi de app nesnemizi kullanarak swagger ve swagger ui kullandığımızı belirtelim.
app.UseSwagger(); app.UseSwaggerUI();
Swagger ayarlarımızı da yaptığımıza göre şimdi Program.cs içerisinde servisimizi register edelim ve Get,Post,Put,Delete metodlarımızı yazalım.
using Microsoft.AspNetCore.Mvc; using Net6MinimalApi.Models; using Net6MinimalApi.Services; var builder = WebApplication.CreateBuilder(args); builder.Services.AddSingleton<IJerseyService, JerseyService>(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); app.UseSwagger(); app.UseSwaggerUI(); #region Api Operaitons #region Get app.MapGet("/jerseys", ([FromServices] IJerseyService jerseyService) => Results.Ok(jerseyService.GetAll())) .Produces<List<Jersey>>(StatusCodes.Status200OK) .WithName("Get All Jersey").WithTags("Jersey"); app.MapGet("/jerseys/{id}", ([FromServices] IJerseyService jerseyService, int id) => { var jersey = jerseyService.Get(id); return jersey != null ? Results.Ok(jersey) : Results.NotFound(); }) .Produces<Jersey>(StatusCodes.Status200OK).Produces(StatusCodes.Status404NotFound) .WithName("Get Spesific Jersey").WithTags("Jersey"); #endregion #region Post app.MapPost("/jerseys", ([FromBody] Jersey jersey, [FromServices] IJerseyService jerseyService) => { var insertedId = jerseyService.Insert(jersey); return insertedId > 0 ? Results.Created("jerseys", insertedId) : Results.BadRequest(); }) .Accepts<Jersey>("application/json") .Produces<int>(StatusCodes.Status201Created).Produces(StatusCodes.Status400BadRequest) .WithName("Add New Jersey").WithTags("Jersey"); #endregion #region Put app.MapPut("/jerseys/{id}", (int id, string playerName, [FromServices] IJerseyService jerseyService) => { var updatedJersey = jerseyService.Update(id, playerName); return updatedJersey != null ? Results.Ok(updatedJersey) : Results.BadRequest(); }) .Produces<Jersey>(StatusCodes.Status200OK).Produces(StatusCodes.Status400BadRequest) .WithName("Update Jersey Player Name").WithTags("Jersey"); #endregion #region Delete app.MapDelete("/jerseys/{id}", (int id, [FromServices] IJerseyService jerseyService) => { var isDeleted = jerseyService.Delete(id); return isDeleted ? Results.Ok() : Results.NotFound(); }) .Produces(StatusCodes.Status200OK).Produces(StatusCodes.Status404NotFound) .WithName("Delete Jersey ").WithTags("Jersey"); #endregion #endregion app.Run("http://localhost:1000"); //Authorize yada AllowAnonymous attributeler ve async gibi keywordler burada kullanılabilir. Örnek kullanım; //app.MapPost("/jerseys", [AllowAnonymous] async ([FromBody] Jersey jersey, [FromServices] IJerseyService jerseyService) => Results.Ok()); //app.MapPost("/jerseys", [Authorize] async ([FromBody] Jersey jersey, [FromServices] IJerseyService jerseyService) => Results.Ok()); //app.MapPost("/jerseys", async ([FromBody] Jersey jersey, [FromServices] IJerseyService jerseyService) => Results.Ok()).RequireAuthorization(); //app.MapPost("/jerseys", async ([FromBody] Jersey jersey, [FromServices] IJerseyService jerseyService) => Results.Ok()).AllowAnonymous(); //app.Run("http://localhost:1000"); // Custom Port //app.Urls.Add("http://localhost:1000"); //app.Urls.Add("http://localhost:1001"); //app.Run() Custom Multiple Port
Projeyi run ederek http://localhost:1000/swagger/index.html adresinden kontrollerimizi gerçekleştirelim.

Umarım faydalı olmuştur arkadaşlar, kalın sağlıcakla…
Github Link : https://github.com/EnesAys/Net6MinimalApi
Kaynaklar
https://devblogs.microsoft.com/dotnet/announcing-net-6/
https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/
https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60-samples?view=aspnetcore-6.0
https://www.youtube.com/watch?v=2chFBs-m1k8
https://medium.com/geekculture/minimal-apis-in-net-6-a-complete-guide-beginners-advanced-fd64f4da07f5