API Create Read Update Delete İşlemleri
CRUD işlemlerini gerçekleştirebilmemiz için küçük bir todo list uygulaması yapacağız iyi okumalar.
API Ayağa Kaldırma
İlk olarak uygulamayı terminal üzerinden oluşturuyoruz. Tabi önce bir versiyon kontrolü yapmakta fayda var uyumsuzluk olmaması için.
dotnet --version
8.0.100
dotnet new web
Bu kodu çalıştırdığımızda bize şu şekilde bir ağaç yapısı vermesi lazım.
├── appsettings.Development.json
├── appsettings.json
├── bin
│ └── Debug
├── obj
│ ├── Debug
│ ├── project.assets.json
│ ├── project.nuget.cache
│ ├── web.csproj.nuget.dgspec.json
│ ├── web.csproj.nuget.g.props
│ └── web.csproj.nuget.g.targets
├── Program.cs
├── Properties
│ └── launchSettings.json
├── req.http
├── r.py
├── web.csproj
└── web.sln
Üzerinde çalışacağımız dosya Program.cs
hızlıca içeriğine bakalım.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
Derinlemesine girmeden kısaca buradan bahsedecek olursak uygulamayı oluşturduğumuz yer.
app.MapGet("/", () => "Hello World!");
Bizi asıl ilgilendiren kısım burası aslında. Oluşturduğumuz app
objesinin MapGet
metot'dunu kullanarak bir API ucu oluşturuyoruz ve program GET isteklerini dinliyor. "/"
bu bizim API ucumuz eğer buraya bir GET isteği atılırsa "Hello World!"
yazısı isteği atan makinaya dönderilecek.
app.Run()
dotnet run
komutu ile uygulamamızı çalıştırdığımızda dotnet
Program.cs
içerisindeki kodları derleyip çalıştıracak. Run()
komutu uygulamamızın sürekli olarak dinleme yapmasını sağlıyor.
Şimdi uygulamayı çalıştıralım ve ne olduğu hakkında biraz daha bilgi sahibi olalım.
user@hostname:~/web$ dotnet run
Building...
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5225
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /home/user/web
Uygulamayı dotnet run
kullanarak çalıştırdığımızda server'dan gelen istekleri dinlemeye hazır. Şimdi uygulamanın bize ne söylediğine tek tek bakalım.
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5225
Uygulama hangi url ve port üzerinde dinleme yaptığını söylüyor. localhost
'da 5225
port'u dinliyor.
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
Uygulamayı nasıl kapatabileceğimizi söylüyor. Ctrl+C
'ye basarak kapatabiliriz.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
Uygulamanın Development
yani geliştirme ortamında çalıştığını söylüyor.
info: Microsoft.Hosting.Lifetime[0]
Content root path: /home/user/web
Uygulamanın çalıştığı dizinin ne olduğunu'da buradan öğrenebiliriz mesela benimki /home/user/web
miş.
Uygulamanı çalıştırdığımıza göre ilk http isteğini atıp ne olduğunu görebiliriz. Tabi bir url'ye istek atmanın bir sürü yolu var ama ben linux kullanıyorum ve python ile istek atmam gerek çünkü racon bu.
import requests as r
def post(url,endpoint,data):
url = url + "/" + endpoint
headers = {"Content-type": "application/json"}
response = r.post(url,json=data, headers=headers)
print(response.status_code,response.text)
def get(url,endpoint):
url = url + "/" + endpoint
response = r.get(url)
print(f"[+] {response.status_code} \n[+] {response.text}")
def delete(url,endpoint):
url = url + "/" + endpoint
response = r.delete(url)
print(f"[+] {response.status_code} \n[+] {response.text}")
Şöyle kısa bir python kodumuz var sunucuya POST
,GET
ve DELETE
istekleri atmamızı sağlıyor ve sunucudan gelen yanıtı terminal ekranına yazdırıyor. Bu kodu uygulamayı çalıştırdığımız dizine .py uzantılı bir dosya olarak kaydediyoruz. Sonrasında python shell'imizi açıyoruz ve sunucumuza bir GET
isteği yolluyoruz.
user@hostname:~/web$ python3
Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import r
>>> url = "http://localhost:5225"
>>> r.get(url,"")
[+] 200
[+] Hello World!
Artık bir çayı hakettik sunucumuz çalışıyor bize 200
status kodu döndü yani istek başarıyla gerçekleşti ve Hello World!
yazısını dönderdi. Şimdi CRUD işlemlerini gerçekleştirebilmemiz için gerekli API uçlarını sunucumuzda oluşturabiliriz. Tabi bunları yazmadan önce server'ımızı kısa bir süreliğine Ctrl+C
ile kapatabiliriz.
CRUD İşlemleri
using Microsoft.AspNetCore.Http.HttpResults;
İlk olarak ihtiyacımız olan kütüphaneleri içe aktarıyoruz.
public record Todo(int Id, string Name, DateTime DueDate, bool IsCompleted);
Verilerimizi saklamamızı kolaylaştırması için bir record objesi oluşturuyoruz.
NOT: Yukarıdaki satırı uygulamanızın en alt satırına yazmanız gerek.
var todos = new List<Todo>();
API ucumuza gelen verileri saklamak için bir liste oluşturuyoruz. Liste sadece Todo
türündeki verileri tutabilir.
Create
İlk API ucumuzu yazma zamanınmız geldi öncelikle CRUD işlemlerinden Create ile başlayalım. Create adından da anlayabileceğiniz üzere verinin oluşturulduğu yerdir. Verinin oluşturulabilmesi için API ucuna veri gönderilmesi gerekir ve bu da POST istekleri ile yapılır. Şimdi POST isteklerini dinleyen bir API ucu yazalım
app.MapPost("/todos", (Todo task) => {
todos.Add(task);
return TypedResults.Created("/todos/{id}",task);
});
Burada kafanıza yatmayan bir yer kalmaması için tek tek inceleyelim.
app
oluşturduğumuz uygulama MapPost
içerisinde bulunan bir method ve POST
isteklerini dinlememizi sağlıyor.
"/todos"
verilerin gönderileceği yer yani istek atılacak adress http://localhost:5225/todos
olmuş oluyor.
(Todo task)
gelen verinin bizim oluşturduğumuz objeye uygun olması gerekiyor. Gönderilen veriler bizim task
objemizdeki değerlerle eşitleniyor. (Bunu birazdan POST isteği attığımız zaman daha iyi anlayacaksınız).
todos.Add(task);
sonrasında bu değerleri daha önceden oluşturduğumuz todos
listesine Add()
methodu ile ekliyoruz.
return TypedResults.Created("/todos/{id}",task);
Kullanıcıya 201 yanıtını ve oluşturduğu objeyi dönderiyoruz. Yani verinin başarıyla oluşturulduğunu söylüyoruz.
Veriyi oluşturduğumuza göre artık onu okuyabiliriz.
Read
Şimdi sakladığımız verileri paylaşma zamanı geldi burada iki api ucu yazacağız birinde verinin tamamını diğerinde ise istenilen veriyi döndereceğiz.
app.MapGet("/todos", () => todos);
Kısa ve öz GET isteklerini MapGet
ile dinliyoruz ve eğer "/todos"
uzantısına bir GET isteği gelirse todos
listemizin tamamını istek atan makinaya döndeririyoruz.
app.MapGet("/todos/{id}", Results<Ok<Todo>, NotFound> (int id) => {
var targetTodo = todos.SingleOrDefault(t => id == t.Id);
return targetTodo is null ? TypedResults.NotFound() :TypedResults.Ok(targetTodo);
});
"/todos/{id}"
gördüğünüz üzere id kısmı süslü parantez içerisinde ve (int id)
olarak fonksiyon içerisine parametre olarak verilmiş yani isteği atan kişi şuna benzer bir istek atacak "/todos/1"
SingleOrDefault(t => id == t.Id);
methodu aracılığı ile gönderilen get isteğindeki id ile liste içerisindeki objelerden id'si eşleşen var mı diye. Bu arama sonucunda elimize ne geçerse bunu targetTodo
içerisinde saklıyoruz. Yani sonuç null veya bir objeye eşit olabilir.
Ve son kısımda eğer targetTodo
null
ise TypedResults.NotFound()
404 status code dönderiyoruz değilse TypedResults.Ok(targetTodo)
200 status code ile bulduğumuz objeyi dönderiyoruz.
Delete
Evet son API ucumuzu yazma zamanı geldi verilerin silineceği API ucu dadada dan.
app.MapDelete("/todos/{id}", (int id) => {
todos.RemoveAll(t => id == t.Id);
return TypedResults.NoContent();
});
MapDelete
methodu DELETE
isteklerini dinliyor. Mesela bir makina böyle bir istek attı "/todos/1"
RemoveAll(t => id == t.Id);
methodu ile bu id'ye sahip bütün objeleri liste içerisinden siliyoruz ve TypedResults.NoContent();
ile 204 status code dönderiyoruz.
Aşağıda kodun tamamını bulabilirsiniz.
using Microsoft.AspNetCore.Http.HttpResults;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// app.MapGet("/", () => "Hello World!");
var todos = new List<Todo>();
app.MapGet("/todos", () => todos);
app.MapGet("/todos/{id}", Results<Ok<Todo>, NotFound> (int id) => {
var targetTodo = todos.SingleOrDefault(t => id == t.Id);
return targetTodo is null ? TypedResults.NotFound() :TypedResults.Ok(targetTodo);
});
app.MapPost("/todos", (Todo task) => {
todos.Add(task);
return TypedResults.Created("/todos/{id}",task);
});
app.MapDelete("/todos/{id}", (int id) => {
todos.RemoveAll(t => id == t.Id);
return TypedResults.NoContent();
});
app.Run();
public record Todo(int Id, string Name, DateTime DueDate, bool IsCompleted);
Test
Şimdi uygulamayı test etme zamanı.
user@hostname:~/web$ dotnet run
Building...
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5225
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /home/user/web
Sunucumuzu çalıştırdık.
user@hostname:~/web$ python3
Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import r
>>> url = "http://localhost:5225"
python
shell'imizi açıyoruz r.py dosyamızı import ediyoruz sonrasında url'mizi bir değişken içerisine atıyoruz.
Şimdi veri oluşturalım (Create).
>>> r.post(url,"todos",{"id":1,"name":"Clear kitchen","dueDate":"2024-03-28T00:00:00","isCompleted":False})
201 {"id":1,"name":"Clear kitchen","dueDate":"2024-03-28T00:00:00","isCompleted":false}
>>> r.post(url,"todos",{"id":2,"name":"Hug your mother","dueDate":"2024-03-28T00:00:00","isCompleted":False})
201 {"id":1,"name":"Hug your mother","dueDate":"2024-03-28T00:00:00","isCompleted":false}
İki tane veri ekledik 201 status code başarıyla eklendiği anlamına geliyor.
Şimdi eklediğimiz verileri okuma zamanı (Read).
>>> r.get(url,"todos")
[+] 200
[+] [{"id":1,"name":"Clear kitchen","dueDate":"2024-03-28T00:00:00","isCompleted":false},{"id":2,"name":"Hug your mother","dueDate":"2024
-03-28T00:00:00","isCompleted":false}]
Güzel ikiside bir liste içerisinde geldi şimdi sadece id'si 2 olanı alalım.
>>> r.get(url,"todos/2")
[+] 200
[+] {"id":2,"name":"Hug your mother","dueDate":"2024-03-28T00:00:00","isCompleted":false}
Son olarak eklediğimiz verilerden bir tanesini silelim.
>>> r.delete(url,"todos/1")
[+] 204
[+]
>>> r.get(url,"todos")
[+] 200
[+] [{"id":2,"name":"Hug your mother","dueDate":"2024-03-28T00:00:00","isCompleted":false}]
Alıştırma
Farkettiyseniz UPDATE 'i yazmadık onu siz yazabilirsiniz :)
Kaynak
Last updated