Öğretici: ASP.NET Core ile minimum API oluşturma
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.
Tarafından Rick Anderson ve Tom Dykstra
Minimum API'ler, en az bağımlılıkla HTTP API'leri oluşturmak için tasarlanır. Bunlar, ASP.NET Core'da yalnızca en düşük dosyaları, özellikleri ve bağımlılıkları dahil etmek isteyen mikro hizmetler ve uygulamalar için idealdir.
Bu öğreticide, ASP.NET Core ile minimum API oluşturmanın temelleri öğretilir. ASP.NET Core'da API oluşturmanın bir diğer yaklaşımı da denetleyicileri kullanmaktır. En düşük API'ler ile denetleyici tabanlı API'ler arasında seçim yaparken yardım için bkz . API'lere genel bakış. Daha fazla özellik içeren denetleyicileri temel alan bir API projesi oluşturma öğreticisi için bkz. Web API'si oluşturma.
Genel bakış
Bu öğretici aşağıdaki API'yi oluşturur:
API | Açıklama | Request body | Yanıt gövdesi |
---|---|---|---|
GET /todoitems |
Tüm yapılacaklar öğelerini alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/complete |
Tamamlanmış yapılacaklar öğeleri alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/{id} |
Öğeyi kimliğine göre alma | Hiçbiri | Yapılacaklar öğesi |
POST /todoitems |
Yeni öğe ekleme | Yapılacaklar öğesi | Yapılacaklar öğesi |
PUT /todoitems/{id} |
Var olan bir öğeyi güncelleştirme | Yapılacaklar öğesi | Hiçbiri |
DELETE /todoitems/{id} |
Öğe silme | Hiçbiri | Hiçbiri |
Önkoşullar
API projesi oluşturma
Visual Studio 2022'yi başlatın ve Yeni proje oluştur'u seçin.
Yeni proje oluştur iletişim kutusunda:
- Şablon ara arama kutusuna girin
Empty
. - ASP.NET Çekirdek Boş şablonunu seçin ve İleri'yi seçin.
- Şablon ara arama kutusuna girin
Projeye TodoApi adını verin ve İleri'yi seçin.
Ek bilgi iletişim kutusunda:
- .NET 9.0 (Önizleme) seçeneğini belirleyin
- Üst düzey deyimleri kullanma seçeneğinin işaretini kaldırın
- Oluştur'u seçin
Kodu inceleme
Dosya Program.cs
aşağıdaki kodu içerir:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Yukarıdaki kod:
- Önceden yapılandırılmış varsayılanlarla bir WebApplicationBuilder ve WebApplication oluşturur.
- döndüren
Hello World!
bir HTTP GET uç noktası/
oluşturur:
Uygulamayı çalıştırma
Hata ayıklayıcı olmadan çalıştırmak için Ctrl+F5 tuşlarına basın.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:
IIS Express SSL sertifikasına güveniyorsanız Evet'i seçin.
Aşağıdaki iletişim kutusu görüntülenir:
Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet'i seçin.
Firefox tarayıcısına güvenme hakkında bilgi için bkz . Firefox SEC_ERROR_INADEQUATE_KEY_USAGE sertifika hatası.
Visual Studio web sunucusunu başlatır Kestrel ve bir tarayıcı penceresi açar.
Hello World!
tarayıcıda görüntülenir. Dosya çok Program.cs
az ama eksiksiz bir uygulama içeriyor.
Tarayıcı penceresini kapatın.
NuGet paketlerini ekleme
Bu öğreticide kullanılan veritabanı ve tanılamayı desteklemek için NuGet paketleri eklenmelidir.
- Araçlar menüsünde NuGet Paket Yöneticisi > Çözüm için NuGet Paketlerini Yönet'i seçin.
- Gözat sekmesini seçin.
- Prelease Ekle'yi seçin.
- Arama kutusuna Microsoft.EntityFrameworkCore.InMemory yazın ve öğesini seçin
Microsoft.EntityFrameworkCore.InMemory
. - Sağ bölmede Proje onay kutusunu ve ardından Yükle'yi seçin.
- Paketi eklemek
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
için önceki yönergeleri izleyin.
Model ve veritabanı bağlam sınıfları
- Proje klasöründe aşağıdaki kodla adlı
Todo.cs
bir dosya oluşturun:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Yukarıdaki kod bu uygulama için modeli oluşturur. Model, uygulamanın yönettiği verileri temsil eden bir sınıftır.
- Aşağıdaki kodla adlı
TodoDb.cs
bir dosya oluşturun:
using Microsoft.EntityFrameworkCore;
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Yukarıdaki kod, bir veri modeli için Entity Framework işlevselliğini koordine eden ana sınıf olan veritabanı bağlamını tanımlar. Bu sınıf sınıfından Microsoft.EntityFrameworkCore.DbContext türetilir.
API kodunu ekleme
Program.cs
dosyasının içeriğini aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Aşağıdaki vurgulanmış kod, veritabanı bağlamını bağımlılık ekleme (DI) kapsayıcısına ekler ve veritabanıyla ilgili özel durumların görüntülenmesini sağlar:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
DI kapsayıcısı, veritabanı bağlamı ve diğer hizmetlere erişim sağlar.
Bu öğreticide API'yi test etmek için Uç Nokta Gezgini ve .http dosyaları kullanılır.
Test deftere nakil verileri
içindeki aşağıdaki kod Program.cs
, bellek içi veritabanına veri ekleyen bir HTTP POST uç noktası /todoitems
oluşturur:
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
Uygulamayı çalıştırma. Artık uç nokta olmadığından /
tarayıcı 404 hatası görüntüler.
POST uç noktası, uygulamaya veri eklemek için kullanılır.
Diğer Windows>Uç Noktalarını Görüntüle>Gezgini'ne tıklayın.
POST uç noktasına sağ tıklayın ve İstek oluştur'a tıklayın.
adlı
TodoApi.http
proje klasöründe, içeriği aşağıdaki örneğe benzer şekilde yeni bir dosya oluşturulur:@TodoApi_HostAddress = https://localhost:7031 Post {{TodoApi_HostAddress}}/todoitems ###
- İlk satır, tüm uç noktalar için kullanılan bir değişken oluşturur.
- Sonraki satır bir POST isteği tanımlar.
- Üçlü hashtag (
###
) satırı bir istek sınırlayıcısıdır: farklı bir istek için bundan sonra gelenler.
POST isteği için üst bilgiler ve bir gövde gerekir. İsteğin bu bölümlerini tanımlamak için POST istek satırının hemen arkasına aşağıdaki satırları ekleyin:
Content-Type: application/json { "name":"walk dog", "isComplete":true }
Yukarıdaki kod bir content-Type üst bilgisi ve JSON istek gövdesi ekler. TodoApi.http dosyası artık aşağıdaki örnekteki gibi görünmelidir, ancak bağlantı noktası numaranızla birlikte:
@TodoApi_HostAddress = https://localhost:7057 Post {{TodoApi_HostAddress}}/todoitems Content-Type: application/json { "name":"walk dog", "isComplete":true } ###
Uygulamayı çalıştırma.
İstek satırının üzerindeki
POST
İstek gönder bağlantısını seçin.POST isteği uygulamaya gönderilir ve yanıt Yanıt bölmesinde görüntülenir.
GET uç noktalarını inceleme
Örnek uygulama çağrısı MapGet
yaparak birkaç GET uç noktası uygular:
API | Açıklama | Request body | Yanıt gövdesi |
---|---|---|---|
GET /todoitems |
Tüm yapılacaklar öğelerini alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/complete |
Tüm tamamlanmış yapılacaklar öğelerini alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/{id} |
Öğeyi kimliğine göre alma | Hiçbiri | Yapılacaklar öğesi |
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
GET uç noktalarını test edin
Bir tarayıcıdan uç noktaları çağırarak GET
veya Uç Nokta Gezgini'ni kullanarak uygulamayı test edin. Aşağıdaki adımlar Uç Nokta Gezgini'ne yöneliktir.
Uç Nokta Gezgini'nde ilk GET uç noktasına sağ tıklayın ve İstek oluştur'a tıklayın.
Dosyaya
TodoApi.http
aşağıdaki içerik eklenir:Get {{TodoApi_HostAddress}}/todoitems ###
Yeni
GET
istek satırının üzerindeki İstek gönder bağlantısını seçin.GET isteği uygulamaya gönderilir ve yanıt Yanıt bölmesinde görüntülenir.
Yanıt gövdesi aşağıdaki JSON'a benzer:
[ { "id": 1, "name": "walk dog", "isComplete": true } ]
Uç Nokta Gezgini'nde GET uç noktasına sağ tıklayın
/todoitems/{id}
ve İstek oluştur'a tıklayın. DosyayaTodoApi.http
aşağıdaki içerik eklenir:GET {{TodoApi_HostAddress}}/todoitems/{id} ###
{id}
öğesini1
ile değiştirin.Yeni GET isteği satırının üzerindeki İstek gönder bağlantısını seçin.
GET isteği uygulamaya gönderilir ve yanıt Yanıt bölmesinde görüntülenir.
Yanıt gövdesi aşağıdaki JSON'a benzer:
{ "id": 1, "name": "walk dog", "isComplete": true }
Bu uygulama bellek içi veritabanı kullanıyor. Uygulama yeniden başlatılırsa GET isteği herhangi bir veri döndürmez. Veri döndürülmezse, uygulamaya POST verileri gönderin ve GET isteğini yeniden deneyin.
Dönüş değerleri
ASP.NET Core, nesneyi otomatik olarak JSON'a serileştirir ve JSON'ı yanıt iletisinin gövdesine yazar. İşlenmeyen özel durum olmadığı varsayılarak, bu dönüş türünün yanıt kodu 200 Tamam'dır. İşlenmeyen özel durumlar 5xx hatalarına çevrilir.
Dönüş türleri çok çeşitli HTTP durum kodlarını temsil edebilir. Örneğin, GET /todoitems/{id}
iki farklı durum değeri döndürebilir:
- İstenen kimlikle eşleşen öğe yoksa, yöntem bir 404 durum NotFound hata kodu döndürür.
- Aksi takdirde, yöntemi bir JSON yanıt gövdesi ile 200 döndürür. Http 200 yanıtında sonuç döndürme
item
.
PUT uç noktasını inceleme
Örnek uygulama kullanarak MapPut
tek bir PUT uç noktası uygular:
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
Bu yöntem yöntemine MapPost
benzer, ancak HTTP PUT kullanır. Başarılı bir yanıt 204 (İçerik Yok) döndürür. HTTP belirtimine göre, PUT isteği istemcinin yalnızca değişiklikleri değil güncelleştirilmiş varlığın tamamını göndermesini gerektirir. Kısmi güncelleştirmeleri desteklemek için HTTP PATCH kullanın.
PUT uç noktasını test edin
Bu örnek, uygulama her başlatıldığında başlatılması gereken bir bellek içi veritabanı kullanır. PUT çağrısından önce veritabanında bir öğe olmalıdır. PUT çağrısı yapmadan önce veritabanında bir öğe olduğundan emin olmak için GET çağrısı yapın.
öğesini içeren ve adını "feed fish"
olarak ayarlayan Id = 1
yapılacaklar öğesini güncelleştirin.
Uç Nokta Gezgini'nde PUT uç noktasına sağ tıklayın ve İstek oluştur'a tıklayın.
Dosyaya
TodoApi.http
aşağıdaki içerik eklenir:Put {{TodoApi_HostAddress}}/todoitems/{id} ###
PUT istek satırında değerini ile
1
değiştirin{id}
.PUT istek satırının hemen arkasına aşağıdaki satırları ekleyin:
Content-Type: application/json { "name": "feed fish", "isComplete": false }
Yukarıdaki kod bir content-Type üst bilgisi ve JSON istek gövdesi ekler.
Yeni PUT istek satırının üzerindeki İstek gönder bağlantısını seçin.
PUT isteği uygulamaya gönderilir ve yanıt Yanıt bölmesinde görüntülenir. Yanıt gövdesi boş ve durum kodu 204'dür.
DELETE uç noktasını inceleme ve test edin
Örnek uygulama kullanarak MapDelete
tek bir DELETE uç noktası uygular:
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
Uç Nokta Gezgini'nde DELETE uç noktasına sağ tıklayın ve İstek oluştur'a tıklayın.
öğesine bir DELETE isteği eklenir
TodoApi.http
.DELETE isteği satırında değerini ile
1
değiştirin{id}
. DELETE isteği aşağıdaki örnekteki gibi görünmelidir:DELETE {{TodoApi_HostAddress}}/todoitems/1 ###
DELETE isteği için İstek gönder bağlantısını seçin.
DELETE isteği uygulamaya gönderilir ve yanıt Yanıt bölmesinde görüntülenir. Yanıt gövdesi boş ve durum kodu 204'dür.
MapGroup API'sini kullanma
Örnek uygulama kodu, her uç nokta ayarlayışında todoitems
URL ön ekini yineler. API'ler genellikle ortak URL ön ekine sahip uç nokta gruplarına sahiptir ve MapGroup bu tür grupların düzenlenmesine yardımcı olmak için yöntemi kullanılabilir. Yinelenen kodu azaltır ve ve WithMetadatagibi RequireAuthorization yöntemlere tek bir çağrıyla tüm uç nokta gruplarını özelleştirmeye olanak tanır.
öğesinin içeriğini Program.cs
aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", async (TodoDb db) =>
await db.Todos.ToListAsync());
todoItems.MapGet("/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
todoItems.MapGet("/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
todoItems.MapPost("/", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
todoItems.MapDelete("/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Yukarıdaki kodda aşağıdaki değişiklikler vardır:
- URL ön ekini
/todoitems
kullanarak grubu ayarlamaya eklervar todoItems = app.MapGroup("/todoitems");
. - Tüm
app.Map<HttpVerb>
yöntemleri olaraktodoItems.Map<HttpVerb>
değiştirir. - Url ön ekini
/todoitems
yöntem çağrılarındanMap<HttpVerb>
kaldırır.
Aynı şekilde çalıştıklarını doğrulamak için uç noktaları test edin.
TypedResults API'sini kullanma
Döndürmenin TypedResults , test edilebilirlik ve uç noktayı açıklamak üzere OpenAPI için yanıt türü meta verilerini otomatik olarak döndürme gibi çeşitli avantajları vardır Results . Daha fazla bilgi için bkz . TypedResults vs Results.
Yöntemler, Map<HttpVerb>
lambda kullanmak yerine yol işleyicisi yöntemlerini çağırabilir. Bir örneği görmek için Program.cs aşağıdaki kodla güncelleştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
app.Run();
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Kod Map<HttpVerb>
artık lambda yerine yöntemleri çağırır:
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
Bu yöntemler uygulayan IResult ve tarafından TypedResultstanımlanan nesneleri döndürür:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Birim testleri bu yöntemleri çağırabilir ve doğru türü döndürdüğünü test edebilir. Örneğin, yöntemi ise GetAllTodos
:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
Birim test kodu, Ok<Todo[]> türünde bir nesnenin işleyici yönteminden döndürüldüğünü doğrulayabilir. Örneğin:
public async Task GetAllTodos_ReturnsOkOfTodosResult()
{
// Arrange
var db = CreateDbContext();
// Act
var result = await TodosApi.GetAllTodos(db);
// Assert: Check for the correct returned type
Assert.IsType<Ok<Todo[]>>(result);
}
Fazla deftere nakledilmesini engelle
Şu anda örnek uygulama tüm Todo
nesneyi kullanıma sunar. Üretim uygulamaları Üretim uygulamalarında, girişi ve döndürülebilecek verileri kısıtlamak için genellikle modelin bir alt kümesi kullanılır. Bunun arkasında birden çok neden vardır ve güvenlik önemli bir nedendir. Modelin alt kümesi genellikle Veri Aktarım Nesnesi (DTO), giriş modeli veya görünüm modeli olarak adlandırılır. DTO bu makalede kullanılmıştır.
DTO şu şekilde kullanılabilir:
- Fazla göndermeyi engelle.
- İstemcilerin görüntülememesi gereken özellikleri gizleyin.
- Yük boyutunu küçültmek için bazı özellikleri atlar.
- İç içe nesneler içeren nesne grafiklerini düzleştirme. Düzleştirilmiş nesne grafikleri istemciler için daha kullanışlı olabilir.
DTO yaklaşımını göstermek için sınıfını bir gizli dizi alanı içerecek şekilde güncelleştirin Todo
:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
Gizli dizi alanının bu uygulamadan gizlenmesi gerekir, ancak bir yönetim uygulaması bunu kullanıma sunma seçeneğini belirleyebilir.
Gizli dizi alanını gönderip alabildiğinizi doğrulayın.
Aşağıdaki kodla adlı TodoItemDTO.cs
bir dosya oluşturun:
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}
Bu DTO modelini kullanmak için dosyanın içeriğini Program.cs
aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
RouteGroupBuilder todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
app.Run();
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Select(x => new TodoItemDTO(x)).ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db) {
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).Select(x => new TodoItemDTO(x)).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(new TodoItemDTO(todo))
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(TodoItemDTO todoItemDTO, TodoDb db)
{
var todoItem = new Todo
{
IsComplete = todoItemDTO.IsComplete,
Name = todoItemDTO.Name
};
db.Todos.Add(todoItem);
await db.SaveChangesAsync();
todoItemDTO = new TodoItemDTO(todoItem);
return TypedResults.Created($"/todoitems/{todoItem.Id}", todoItemDTO);
}
static async Task<IResult> UpdateTodo(int id, TodoItemDTO todoItemDTO, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = todoItemDTO.Name;
todo.IsComplete = todoItemDTO.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Gizli dizi alanı dışındaki tüm alanları gönderip alabildiğinizi doğrulayın.
Tamamlanan örnekle ilgili sorun giderme
Çözemediğiniz bir sorunla karşılaşırsanız kodunuzu tamamlanmış projeyle karşılaştırın. Tamamlanan projeyi görüntüleme veya indirme (indirme).
Sonraki adımlar
- JSON serileştirme seçeneklerini yapılandırın.
- Hataları ve özel durumları işleme: Geliştirici özel durum sayfası , minimum API uygulamaları için geliştirme ortamında varsayılan olarak etkindir. Hataları ve özel durumları işleme hakkında bilgi için bkz . ASP.NET Core API'lerindeki hataları işleme.
- En düşük API uygulamasını test etme örneği için bu GitHub örneğine bakın.
- Minimum API'lerde OpenAPI desteği.
- Hızlı Başlangıç: Azure'da yayımlama.
- ASP.NET Temel Minimum API'leri düzenleme.
Daha fazla bilgi edinin
Minimum API'ler, en az bağımlılıkla HTTP API'leri oluşturmak için tasarlanır. Bunlar, ASP.NET Core'da yalnızca en düşük dosyaları, özellikleri ve bağımlılıkları dahil etmek isteyen mikro hizmetler ve uygulamalar için idealdir.
Bu öğreticide, ASP.NET Core ile minimum API oluşturmanın temelleri öğretilir. ASP.NET Core'da API oluşturmanın bir diğer yaklaşımı da denetleyicileri kullanmaktır. En düşük API'ler ile denetleyici tabanlı API'ler arasında seçim yaparken yardım için bkz . API'lere genel bakış. Daha fazla özellik içeren denetleyicileri temel alan bir API projesi oluşturma öğreticisi için bkz. Web API'si oluşturma.
Genel bakış
Bu öğretici aşağıdaki API'yi oluşturur:
API | Açıklama | Request body | Yanıt gövdesi |
---|---|---|---|
GET /todoitems |
Tüm yapılacaklar öğelerini alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/complete |
Tamamlanmış yapılacaklar öğeleri alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/{id} |
Öğeyi kimliğine göre alma | Hiçbiri | Yapılacaklar öğesi |
POST /todoitems |
Yeni öğe ekleme | Yapılacaklar öğesi | Yapılacaklar öğesi |
PUT /todoitems/{id} |
Var olan bir öğeyi güncelleştirme | Yapılacaklar öğesi | Hiçbiri |
DELETE /todoitems/{id} |
Öğe silme | Hiçbiri | Hiçbiri |
Önkoşullar
Visual Studio 2022 ile ASP.NET ve web geliştirme iş yükü.
API projesi oluşturma
Visual Studio 2022'yi başlatın ve Yeni proje oluştur'u seçin.
Yeni proje oluştur iletişim kutusunda:
- Şablon ara arama kutusuna girin
Empty
. - ASP.NET Çekirdek Boş şablonunu seçin ve İleri'yi seçin.
- Şablon ara arama kutusuna girin
Projeye TodoApi adını verin ve İleri'yi seçin.
Ek bilgi iletişim kutusunda:
- .NET 7.0'ı seçin
- Üst düzey deyimleri kullanma seçeneğinin işaretini kaldırın
- Oluştur'u seçin
Kodu inceleme
Dosya Program.cs
aşağıdaki kodu içerir:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Yukarıdaki kod:
- Önceden yapılandırılmış varsayılanlarla bir WebApplicationBuilder ve WebApplication oluşturur.
- döndüren
Hello World!
bir HTTP GET uç noktası/
oluşturur:
Uygulamayı çalıştırma
Hata ayıklayıcı olmadan çalıştırmak için Ctrl+F5 tuşlarına basın.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:
IIS Express SSL sertifikasına güveniyorsanız Evet'i seçin.
Aşağıdaki iletişim kutusu görüntülenir:
Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet'i seçin.
Firefox tarayıcısına güvenme hakkında bilgi için bkz . Firefox SEC_ERROR_INADEQUATE_KEY_USAGE sertifika hatası.
Visual Studio web sunucusunu başlatır Kestrel ve bir tarayıcı penceresi açar.
Hello World!
tarayıcıda görüntülenir. Dosya çok Program.cs
az ama eksiksiz bir uygulama içeriyor.
NuGet paketlerini ekleme
Bu öğreticide kullanılan veritabanı ve tanılamayı desteklemek için NuGet paketleri eklenmelidir.
- Araçlar menüsünde NuGet Paket Yöneticisi > Çözüm için NuGet Paketlerini Yönet'i seçin.
- Gözat sekmesini seçin.
- Arama kutusuna Microsoft.EntityFrameworkCore.InMemory yazın ve öğesini seçin
Microsoft.EntityFrameworkCore.InMemory
. - Sağ bölmede Proje onay kutusunu seçin.
- Sürüm açılan listesinde, kullanılabilir en son sürüm 7'yi (örneğin
7.0.17
) seçin ve ardından Yükle'yi seçin. - Paketi kullanılabilir en son sürüm 7 ile eklemek
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
için önceki yönergeleri izleyin.
Model ve veritabanı bağlam sınıfları
Proje klasöründe aşağıdaki kodla adlı Todo.cs
bir dosya oluşturun:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Yukarıdaki kod bu uygulama için modeli oluşturur. Model, uygulamanın yönettiği verileri temsil eden bir sınıftır.
Aşağıdaki kodla adlı TodoDb.cs
bir dosya oluşturun:
using Microsoft.EntityFrameworkCore;
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Yukarıdaki kod, bir veri modeli için Entity Framework işlevselliğini koordine eden ana sınıf olan veritabanı bağlamını tanımlar. Bu sınıf sınıfından Microsoft.EntityFrameworkCore.DbContext türetilir.
API kodunu ekleme
Program.cs
dosyasının içeriğini aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Aşağıdaki vurgulanmış kod, veritabanı bağlamını bağımlılık ekleme (DI) kapsayıcısına ekler ve veritabanıyla ilgili özel durumların görüntülenmesini sağlar:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
DI kapsayıcısı, veritabanı bağlamı ve diğer hizmetlere erişim sağlar.
Swagger ile API test kullanıcı arabirimi oluşturma
Aralarından seçim yapabileceğiniz birçok kullanılabilir web API'si test aracı vardır ve tercih ettiğiniz araçla bu öğreticinin giriş API testi adımlarını izleyebilirsiniz.
Bu öğreticide, OpenAPI belirtimine uygun bir test kullanıcı arabirimi oluşturmak için Swagger araçlarını tümleştiren .NET paketi NSwag.AspNetCore kullanılır:
- NSwag: Swagger'ı doğrudan ASP.NET Core uygulamalarıyla tümleştirerek ara yazılım ve yapılandırma sağlayan bir .NET kitaplığı.
- Swagger: OpenAPI belirtimini izleyen API test sayfaları oluşturan OpenAPIGenerator ve SwaggerUI gibi açık kaynak araçlar kümesi.
- OpenAPI belirtimi: Denetleyiciler ve modeller içindeki XML ve öznitelik ek açıklamalarını temel alarak API'nin özelliklerini açıklayan belge.
ASP.NET ile OpenAPI ve NSwag kullanma hakkında daha fazla bilgi için Swagger / OpenAPI ile ASP.NET Core web API belgelerine bakın.
Swagger araçlarını yükleme
Şu komutu çalıştırın:
dotnet add package NSwag.AspNetCore
Önceki komut, Swagger belgeleri ve kullanıcı arabirimi oluşturmaya yönelik araçlar içeren NSwag.AspNetCore paketini ekler.
Swagger ara yazılımını yapılandırma
Satırda tanımlanmadan önce
app
aşağıdaki vurgulanmış kodu ekleyinvar app = builder.Build();
using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList")); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddOpenApiDocument(config => { config.DocumentName = "TodoAPI"; config.Title = "TodoAPI v1"; config.Version = "v1"; }); var app = builder.Build();
Önceki kodda:
builder.Services.AddEndpointsApiExplorer();
: HTTP API hakkında meta veriler sağlayan bir hizmet olan API Gezgini'ni etkinleştirir. API Gezgini, Swagger tarafından Swagger belgesini oluşturmak için kullanılır.builder.Services.AddOpenApiDocument(config => {...});
: Swagger OpenAPI belge oluşturucusunu uygulama hizmetlerine ekler ve API hakkında başlığı ve sürümü gibi daha fazla bilgi sağlayacak şekilde yapılandırılır. Daha sağlam API ayrıntıları sağlama hakkında bilgi için bkz . NSwag ve ASP.NET Core kullanmaya başlamaSatırda tanımlandıktan sonra
app
aşağıdaki vurgulanmış kodu sonraki satıra ekleyinvar app = builder.Build();
var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseOpenApi(); app.UseSwaggerUi(config => { config.DocumentTitle = "TodoAPI"; config.Path = "/swagger"; config.DocumentPath = "/swagger/{documentName}/swagger.json"; config.DocExpansion = "list"; }); }
Önceki kod, Swagger ara yazılımının oluşturulan JSON belgesini ve Swagger kullanıcı arabirimini sunmasını sağlar. Swagger yalnızca geliştirme ortamında etkinleştirilir. Bir üretim ortamında Swagger'ın etkinleştirilmesi, API'nin yapısı ve uygulaması hakkında hassas olabilecek ayrıntıları ortaya çıkarabilir.
Test deftere nakil verileri
içindeki aşağıdaki kod Program.cs
, bellek içi veritabanına veri ekleyen bir HTTP POST uç noktası /todoitems
oluşturur:
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
Uygulamayı çalıştırma. Artık uç nokta olmadığından /
tarayıcı 404 hatası görüntüler.
POST uç noktası, uygulamaya veri eklemek için kullanılır.
Uygulama çalışmaya devam ettiği için
https://localhost:<port>/swagger
tarayıcıda Swagger tarafından oluşturulan API test sayfasını görüntülemek için adresine gidin.Swagger API testi sayfasında Gönder /todoitems>Deneyin'i seçin.
İstek gövdesi alanında API parametrelerini yansıtan oluşturulmuş bir örnek biçimi olduğuna dikkat edin.
İstek gövdesine, isteğe bağlı
id
öğesini belirtmeden yapılacaklar öğesi için JSON girin:{ "name":"walk dog", "isComplete":true }
Yürüt'ü seçin.
Swagger, Yürüt düğmesinin altında bir Yanıtlar bölmesi sağlar.
Yararlı ayrıntılardan birkaçını not edin:
- cURL: Swagger Unix/Linux söz diziminde örnek bir cURL komutu sağlar. Bu komut, Windows için Git'ten Git Bash de dahil olmak üzere Unix/Linux söz dizimi kullanan herhangi bir bash kabuğuyla komut satırında çalıştırılabilir.
- İstek URL'si: Swagger UI'nin API çağrısı için JavaScript kodu tarafından yapılan HTTP isteğinin basitleştirilmiş bir gösterimi. Gerçek istekler üst bilgiler, sorgu parametreleri ve istek gövdesi gibi ayrıntıları içerebilir.
- Sunucu yanıtı: Yanıt gövdesini ve üst bilgileri içerir. Yanıt gövdesi, olarak
id
ayarlandığını1
gösterir. - Yanıt Kodu: İsteğin başarıyla işlendiğini ve yeni bir kaynak oluşturulmasıyla sonuçlandığını belirten bir 201
HTTP
durum kodu döndürüldü.
GET uç noktalarını inceleme
Örnek uygulama çağrısı MapGet
yaparak birkaç GET uç noktası uygular:
API | Açıklama | Request body | Yanıt gövdesi |
---|---|---|---|
GET /todoitems |
Tüm yapılacaklar öğelerini alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/complete |
Tüm tamamlanmış yapılacaklar öğelerini alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/{id} |
Öğeyi kimliğine göre alma | Hiçbiri | Yapılacaklar öğesi |
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
GET uç noktalarını test edin
Bir tarayıcıdan veya Swagger'dan uç noktaları çağırarak uygulamayı test edin.
Swagger'da GET /todoitems Try it out>Execute öğesini seçin.>
Alternatif olarak, URI'sini
http://localhost:<port>/todoitems
girerek tarayıcıdan GET /todoitems öğesini çağırın. Örneğinhttp://localhost:5001/todoitems
çağrısı aşağıdakine GET /todoitems
benzer bir yanıt oluşturur:
[
{
"id": 1,
"name": "walk dog",
"isComplete": true
}
]
Belirli bir kimlikten veri döndürmek için Swagger'da GET /todoitems/{id} çağrısı yapın:
- GET /todoitems>Try it öğesini seçin.
- Kimlik alanını olarak
1
ayarlayın ve Yürüt'e tıklayın.
Alternatif olarak, URI'sini
https://localhost:<port>/todoitems/1
girerek tarayıcıdan GET /todoitems öğesini çağırın. Örneğinhttps://localhost:5001/todoitems/1
Yanıt aşağıdakine benzer:
{ "id": 1, "name": "walk dog", "isComplete": true }
Bu uygulama bellek içi veritabanı kullanıyor. Uygulama yeniden başlatılırsa GET isteği herhangi bir veri döndürmez. Veri döndürülmezse, uygulamaya POST verileri gönderin ve GET isteğini yeniden deneyin.
Dönüş değerleri
ASP.NET Core, nesneyi otomatik olarak JSON'a serileştirir ve JSON'ı yanıt iletisinin gövdesine yazar. İşlenmeyen özel durum olmadığı varsayılarak, bu dönüş türünün yanıt kodu 200 Tamam'dır. İşlenmeyen özel durumlar 5xx hatalarına çevrilir.
Dönüş türleri çok çeşitli HTTP durum kodlarını temsil edebilir. Örneğin, GET /todoitems/{id}
iki farklı durum değeri döndürebilir:
- İstenen kimlikle eşleşen öğe yoksa, yöntem bir 404 durum NotFound hata kodu döndürür.
- Aksi takdirde, yöntemi bir JSON yanıt gövdesi ile 200 döndürür. Http 200 yanıtında sonuç döndürme
item
.
PUT uç noktasını inceleme
Örnek uygulama kullanarak MapPut
tek bir PUT uç noktası uygular:
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
Bu yöntem yöntemine MapPost
benzer, ancak HTTP PUT kullanır. Başarılı bir yanıt 204 (İçerik Yok) döndürür. HTTP belirtimine göre, PUT isteği istemcinin yalnızca değişiklikleri değil güncelleştirilmiş varlığın tamamını göndermesini gerektirir. Kısmi güncelleştirmeleri desteklemek için HTTP PATCH kullanın.
PUT uç noktasını test edin
Bu örnek, uygulama her başlatıldığında başlatılması gereken bir bellek içi veritabanı kullanır. PUT çağrısından önce veritabanında bir öğe olmalıdır. PUT çağrısı yapmadan önce veritabanında bir öğe olduğundan emin olmak için GET çağrısı yapın.
öğesini içeren ve adını "feed fish"
olarak ayarlayan Id = 1
yapılacaklar öğesini güncelleştirin.
PUT isteği göndermek için Swagger kullanın:
Koy /todoitems/{id}>Deneyin'i seçin.
Kimlik alanını olarak
1
ayarlayın.İstek gövdesini aşağıdaki JSON olarak ayarlayın:
{ "name": "feed fish", "isComplete": false }
Yürüt'ü seçin.
DELETE uç noktasını inceleme ve test edin
Örnek uygulama kullanarak MapDelete
tek bir DELETE uç noktası uygular:
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
DELETE isteği göndermek için Swagger'ı kullanın:
DELETE /todoitems/{id}>Deneyin'i seçin.
Kimlik alanını olarak
1
ayarlayın ve Yürüt'e tıklayın.DELETE isteği uygulamaya gönderilir ve yanıt Yanıtlar bölmesinde görüntülenir. Yanıt gövdesi boş ve Sunucu yanıt durumu kodu 204'dür.
MapGroup API'sini kullanma
Örnek uygulama kodu, her uç nokta ayarlayışında todoitems
URL ön ekini yineler. API'ler genellikle ortak URL ön ekine sahip uç nokta gruplarına sahiptir ve MapGroup bu tür grupların düzenlenmesine yardımcı olmak için yöntemi kullanılabilir. Yinelenen kodu azaltır ve ve WithMetadatagibi RequireAuthorization yöntemlere tek bir çağrıyla tüm uç nokta gruplarını özelleştirmeye olanak tanır.
öğesinin içeriğini Program.cs
aşağıdaki kodla değiştirin:
using NSwag.AspNetCore;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddOpenApiDocument(config =>
{
config.DocumentName = "TodoAPI";
config.Title = "TodoAPI v1";
config.Version = "v1";
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseOpenApi();
app.UseSwaggerUi(config =>
{
config.DocumentTitle = "TodoAPI";
config.Path = "/swagger";
config.DocumentPath = "/swagger/{documentName}/swagger.json";
config.DocExpansion = "list";
});
}
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", async (TodoDb db) =>
await db.Todos.ToListAsync());
todoItems.MapGet("/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
todoItems.MapGet("/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
todoItems.MapPost("/", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
todoItems.MapDelete("/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Yukarıdaki kodda aşağıdaki değişiklikler vardır:
- URL ön ekini
/todoitems
kullanarak grubu ayarlamaya eklervar todoItems = app.MapGroup("/todoitems");
. - Tüm
app.Map<HttpVerb>
yöntemleri olaraktodoItems.Map<HttpVerb>
değiştirir. - Url ön ekini
/todoitems
yöntem çağrılarındanMap<HttpVerb>
kaldırır.
Aynı şekilde çalıştıklarını doğrulamak için uç noktaları test edin.
TypedResults API'sini kullanma
Döndürmenin TypedResults , test edilebilirlik ve uç noktayı açıklamak üzere OpenAPI için yanıt türü meta verilerini otomatik olarak döndürme gibi çeşitli avantajları vardır Results . Daha fazla bilgi için bkz . TypedResults vs Results.
Yöntemler, Map<HttpVerb>
lambda kullanmak yerine yol işleyicisi yöntemlerini çağırabilir. Bir örneği görmek için Program.cs aşağıdaki kodla güncelleştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
app.Run();
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Kod Map<HttpVerb>
artık lambda yerine yöntemleri çağırır:
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
Bu yöntemler uygulayan IResult ve tarafından TypedResultstanımlanan nesneleri döndürür:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Birim testleri bu yöntemleri çağırabilir ve doğru türü döndürdüğünü test edebilir. Örneğin, yöntemi ise GetAllTodos
:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
Birim test kodu, Ok<Todo[]> türünde bir nesnenin işleyici yönteminden döndürüldüğünü doğrulayabilir. Örneğin:
public async Task GetAllTodos_ReturnsOkOfTodosResult()
{
// Arrange
var db = CreateDbContext();
// Act
var result = await TodosApi.GetAllTodos(db);
// Assert: Check for the correct returned type
Assert.IsType<Ok<Todo[]>>(result);
}
Fazla deftere nakledilmesini engelle
Şu anda örnek uygulama tüm Todo
nesneyi kullanıma sunar. Üretim uygulamaları Üretim uygulamalarında, girişi ve döndürülebilecek verileri kısıtlamak için genellikle modelin bir alt kümesi kullanılır. Bunun arkasında birden çok neden vardır ve güvenlik önemli bir nedendir. Modelin alt kümesi genellikle Veri Aktarım Nesnesi (DTO), giriş modeli veya görünüm modeli olarak adlandırılır. DTO bu makalede kullanılmıştır.
DTO şu şekilde kullanılabilir:
- Fazla göndermeyi engelle.
- İstemcilerin görüntülememesi gereken özellikleri gizleyin.
- Yük boyutunu küçültmek için bazı özellikleri atlar.
- İç içe nesneler içeren nesne grafiklerini düzleştirme. Düzleştirilmiş nesne grafikleri istemciler için daha kullanışlı olabilir.
DTO yaklaşımını göstermek için sınıfını bir gizli dizi alanı içerecek şekilde güncelleştirin Todo
:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
Gizli dizi alanının bu uygulamadan gizlenmesi gerekir, ancak bir yönetim uygulaması bunu kullanıma sunma seçeneğini belirleyebilir.
Gizli dizi alanını gönderip alabildiğinizi doğrulayın.
Aşağıdaki kodla adlı TodoItemDTO.cs
bir dosya oluşturun:
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}
Bu DTO modelini kullanmak için dosyanın içeriğini Program.cs
aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
var app = builder.Build();
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.Select(x => new TodoItemDTO(x)).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(new TodoItemDTO(todo))
: Results.NotFound());
app.MapPost("/todoitems", async (TodoItemDTO todoItemDTO, TodoDb db) =>
{
var todoItem = new Todo
{
IsComplete = todoItemDTO.IsComplete,
Name = todoItemDTO.Name
};
db.Todos.Add(todoItem);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todoItem.Id}", new TodoItemDTO(todoItem));
});
app.MapPut("/todoitems/{id}", async (int id, TodoItemDTO todoItemDTO, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = todoItemDTO.Name;
todo.IsComplete = todoItemDTO.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Gizli dizi alanı dışındaki tüm alanları gönderip alabildiğinizi doğrulayın.
Tamamlanan örnekle ilgili sorun giderme
Çözemediğiniz bir sorunla karşılaşırsanız kodunuzu tamamlanmış projeyle karşılaştırın. Tamamlanan projeyi görüntüleme veya indirme (indirme).
Sonraki adımlar
- JSON serileştirme seçeneklerini yapılandırın.
- Hataları ve özel durumları işleme: Geliştirici özel durum sayfası , minimum API uygulamaları için geliştirme ortamında varsayılan olarak etkindir. Hataları ve özel durumları işleme hakkında bilgi için bkz . ASP.NET Core API'lerindeki hataları işleme.
- En düşük API uygulamasını test etme örneği için bu GitHub örneğine bakın.
- Minimum API'lerde OpenAPI desteği.
- Hızlı Başlangıç: Azure'da yayımlama.
- ASP.NET Temel Minimum API'leri düzenleme.
Daha fazla bilgi edinin
Minimum API'ler, en az bağımlılıkla HTTP API'leri oluşturmak için tasarlanır. Bunlar, ASP.NET Core'da yalnızca en düşük dosyaları, özellikleri ve bağımlılıkları dahil etmek isteyen mikro hizmetler ve uygulamalar için idealdir.
Bu öğreticide, ASP.NET Core ile minimum API oluşturmanın temelleri öğretilir. ASP.NET Core'da API oluşturmanın bir diğer yaklaşımı da denetleyicileri kullanmaktır. En düşük API'ler ile denetleyici tabanlı API'ler arasında seçim yaparken yardım için bkz . API'lere genel bakış. Daha fazla özellik içeren denetleyicileri temel alan bir API projesi oluşturma öğreticisi için bkz. Web API'si oluşturma.
Genel bakış
Bu öğretici aşağıdaki API'yi oluşturur:
API | Açıklama | Request body | Yanıt gövdesi |
---|---|---|---|
GET /todoitems |
Tüm yapılacaklar öğelerini alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/complete |
Tamamlanmış yapılacaklar öğeleri alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/{id} |
Öğeyi kimliğine göre alma | Hiçbiri | Yapılacaklar öğesi |
POST /todoitems |
Yeni öğe ekleme | Yapılacaklar öğesi | Yapılacaklar öğesi |
PUT /todoitems/{id} |
Var olan bir öğeyi güncelleştirme | Yapılacaklar öğesi | Hiçbiri |
DELETE /todoitems/{id} |
Öğe silme | Hiçbiri | Hiçbiri |
Önkoşullar
- Visual Studio 2022 ile ASP.NET ve web geliştirme iş yükü.
- .NET 6.0 SDK
API projesi oluşturma
Visual Studio 2022'yi başlatın ve Yeni proje oluştur'u seçin.
Yeni proje oluştur iletişim kutusunda:
- Şablon ara arama kutusuna girin
Empty
. - ASP.NET Çekirdek Boş şablonunu seçin ve İleri'yi seçin.
- Şablon ara arama kutusuna girin
Projeye TodoApi adını verin ve İleri'yi seçin.
Ek bilgi iletişim kutusunda:
- .NET 6.0'ı seçin
- Üst düzey deyimleri kullanma seçeneğinin işaretini kaldırın
- Oluştur'u seçin
Kodu inceleme
Dosya Program.cs
aşağıdaki kodu içerir:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Yukarıdaki kod:
- Önceden yapılandırılmış varsayılanlarla bir WebApplicationBuilder ve WebApplication oluşturur.
- döndüren
Hello World!
bir HTTP GET uç noktası/
oluşturur:
Uygulamayı çalıştırma
Hata ayıklayıcı olmadan çalıştırmak için Ctrl+F5 tuşlarına basın.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:
IIS Express SSL sertifikasına güveniyorsanız Evet'i seçin.
Aşağıdaki iletişim kutusu görüntülenir:
Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet'i seçin.
Firefox tarayıcısına güvenme hakkında bilgi için bkz . Firefox SEC_ERROR_INADEQUATE_KEY_USAGE sertifika hatası.
Visual Studio web sunucusunu başlatır Kestrel ve bir tarayıcı penceresi açar.
Hello World!
tarayıcıda görüntülenir. Dosya çok Program.cs
az ama eksiksiz bir uygulama içeriyor.
NuGet paketlerini ekleme
Bu öğreticide kullanılan veritabanı ve tanılamayı desteklemek için NuGet paketleri eklenmelidir.
- Araçlar menüsünde NuGet Paket Yöneticisi > Çözüm için NuGet Paketlerini Yönet'i seçin.
- Gözat sekmesini seçin.
- Arama kutusuna Microsoft.EntityFrameworkCore.InMemory yazın ve öğesini seçin
Microsoft.EntityFrameworkCore.InMemory
. - Sağ bölmede Proje onay kutusunu seçin.
- Sürüm açılan listesinde, kullanılabilir en son sürüm 7'yi (örneğin
6.0.28
) seçin ve ardından Yükle'yi seçin. - Paketi kullanılabilir en son sürüm 7 ile eklemek
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
için önceki yönergeleri izleyin.
Model ve veritabanı bağlam sınıfları
Proje klasöründe aşağıdaki kodla adlı Todo.cs
bir dosya oluşturun:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Yukarıdaki kod bu uygulama için modeli oluşturur. Model, uygulamanın yönettiği verileri temsil eden bir sınıftır.
Aşağıdaki kodla adlı TodoDb.cs
bir dosya oluşturun:
using Microsoft.EntityFrameworkCore;
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Yukarıdaki kod, bir veri modeli için Entity Framework işlevselliğini koordine eden ana sınıf olan veritabanı bağlamını tanımlar. Bu sınıf sınıfından Microsoft.EntityFrameworkCore.DbContext türetilir.
API kodunu ekleme
Program.cs
dosyasının içeriğini aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Aşağıdaki vurgulanmış kod, veritabanı bağlamını bağımlılık ekleme (DI) kapsayıcısına ekler ve veritabanıyla ilgili özel durumların görüntülenmesini sağlar:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
DI kapsayıcısı, veritabanı bağlamı ve diğer hizmetlere erişim sağlar.
Swagger ile API test kullanıcı arabirimi oluşturma
Aralarından seçim yapabileceğiniz birçok kullanılabilir web API'si test aracı vardır ve tercih ettiğiniz araçla bu öğreticinin giriş API testi adımlarını izleyebilirsiniz.
Bu öğreticide, OpenAPI belirtimine uygun bir test kullanıcı arabirimi oluşturmak için Swagger araçlarını tümleştiren .NET paketi NSwag.AspNetCore kullanılır:
- NSwag: Swagger'ı doğrudan ASP.NET Core uygulamalarıyla tümleştirerek ara yazılım ve yapılandırma sağlayan bir .NET kitaplığı.
- Swagger: OpenAPI belirtimini izleyen API test sayfaları oluşturan OpenAPIGenerator ve SwaggerUI gibi açık kaynak araçlar kümesi.
- OpenAPI belirtimi: Denetleyiciler ve modeller içindeki XML ve öznitelik ek açıklamalarını temel alarak API'nin özelliklerini açıklayan belge.
ASP.NET ile OpenAPI ve NSwag kullanma hakkında daha fazla bilgi için Swagger / OpenAPI ile ASP.NET Core web API belgelerine bakın.
Swagger araçlarını yükleme
Şu komutu çalıştırın:
dotnet add package NSwag.AspNetCore
Önceki komut, Swagger belgeleri ve kullanıcı arabirimi oluşturmaya yönelik araçlar içeren NSwag.AspNetCore paketini ekler.
Swagger ara yazılımını yapılandırma
Program.cs üst kısmına aşağıdaki
using
deyimleri ekleyin:using NSwag.AspNetCore;
Satırda tanımlanmadan önce
app
aşağıdaki vurgulanmış kodu ekleyinvar app = builder.Build();
using NSwag.AspNetCore; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList")); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddOpenApiDocument(config => { config.DocumentName = "TodoAPI"; config.Title = "TodoAPI v1"; config.Version = "v1"; }); var app = builder.Build();
Önceki kodda:
builder.Services.AddEndpointsApiExplorer();
: HTTP API hakkında meta veriler sağlayan bir hizmet olan API Gezgini'ni etkinleştirir. API Gezgini, Swagger tarafından Swagger belgesini oluşturmak için kullanılır.builder.Services.AddOpenApiDocument(config => {...});
: Swagger OpenAPI belge oluşturucusunu uygulama hizmetlerine ekler ve API hakkında başlığı ve sürümü gibi daha fazla bilgi sağlayacak şekilde yapılandırılır. Daha sağlam API ayrıntıları sağlama hakkında bilgi için bkz . NSwag ve ASP.NET Core kullanmaya başlamaSatırda tanımlandıktan sonra
app
aşağıdaki vurgulanmış kodu sonraki satıra ekleyinvar app = builder.Build();
var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseOpenApi(); app.UseSwaggerUi(config => { config.DocumentTitle = "TodoAPI"; config.Path = "/swagger"; config.DocumentPath = "/swagger/{documentName}/swagger.json"; config.DocExpansion = "list"; }); }
Önceki kod, Swagger ara yazılımının oluşturulan JSON belgesini ve Swagger kullanıcı arabirimini sunmasını sağlar. Swagger yalnızca geliştirme ortamında etkinleştirilir. Bir üretim ortamında Swagger'ın etkinleştirilmesi, API'nin yapısı ve uygulaması hakkında hassas olabilecek ayrıntıları ortaya çıkarabilir.
Test deftere nakil verileri
içindeki aşağıdaki kod Program.cs
, bellek içi veritabanına veri ekleyen bir HTTP POST uç noktası /todoitems
oluşturur:
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
Uygulamayı çalıştırma. Artık uç nokta olmadığından /
tarayıcı 404 hatası görüntüler.
POST uç noktası, uygulamaya veri eklemek için kullanılır.
Uygulama çalışmaya devam ettiği için
https://localhost:<port>/swagger
tarayıcıda Swagger tarafından oluşturulan API test sayfasını görüntülemek için adresine gidin.Swagger API testi sayfasında Gönder /todoitems>Deneyin'i seçin.
İstek gövdesi alanında API parametrelerini yansıtan oluşturulmuş bir örnek biçimi olduğuna dikkat edin.
İstek gövdesine, isteğe bağlı
id
öğesini belirtmeden yapılacaklar öğesi için JSON girin:{ "name":"walk dog", "isComplete":true }
Yürüt'ü seçin.
Swagger, Yürüt düğmesinin altında bir Yanıtlar bölmesi sağlar.
Yararlı ayrıntılardan birkaçını not edin:
- cURL: Swagger Unix/Linux söz diziminde örnek bir cURL komutu sağlar. Bu komut, Windows için Git'ten Git Bash de dahil olmak üzere Unix/Linux söz dizimi kullanan herhangi bir bash kabuğuyla komut satırında çalıştırılabilir.
- İstek URL'si: Swagger UI'nin API çağrısı için JavaScript kodu tarafından yapılan HTTP isteğinin basitleştirilmiş bir gösterimi. Gerçek istekler üst bilgiler, sorgu parametreleri ve istek gövdesi gibi ayrıntıları içerebilir.
- Sunucu yanıtı: Yanıt gövdesini ve üst bilgileri içerir. Yanıt gövdesi, olarak
id
ayarlandığını1
gösterir. - Yanıt Kodu: İsteğin başarıyla işlendiğini ve yeni bir kaynak oluşturulmasıyla sonuçlandığını belirten bir 201
HTTP
durum kodu döndürüldü.
GET uç noktalarını inceleme
Örnek uygulama çağrısı MapGet
yaparak birkaç GET uç noktası uygular:
API | Açıklama | Request body | Yanıt gövdesi |
---|---|---|---|
GET /todoitems |
Tüm yapılacaklar öğelerini alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/complete |
Tüm tamamlanmış yapılacaklar öğelerini alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/{id} |
Öğeyi kimliğine göre alma | Hiçbiri | Yapılacaklar öğesi |
app.MapGet("/", () => "Hello World!");
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
GET uç noktalarını test edin
Bir tarayıcıdan veya Swagger'dan uç noktaları çağırarak uygulamayı test edin.
Swagger'da GET /todoitems Try it out>Execute öğesini seçin.>
Alternatif olarak, URI'sini
http://localhost:<port>/todoitems
girerek tarayıcıdan GET /todoitems öğesini çağırın. Örneğinhttp://localhost:5001/todoitems
çağrısı aşağıdakine GET /todoitems
benzer bir yanıt oluşturur:
[
{
"id": 1,
"name": "walk dog",
"isComplete": true
}
]
Belirli bir kimlikten veri döndürmek için Swagger'da GET /todoitems/{id} çağrısı yapın:
- GET /todoitems>Try it öğesini seçin.
- Kimlik alanını olarak
1
ayarlayın ve Yürüt'e tıklayın.
Alternatif olarak, URI'sini
https://localhost:<port>/todoitems/1
girerek tarayıcıdan GET /todoitems öğesini çağırın. Örneğin, Örneğin,https://localhost:5001/todoitems/1
Yanıt aşağıdakine benzer:
{ "id": 1, "name": "walk dog", "isComplete": true }
Bu uygulama bellek içi veritabanı kullanıyor. Uygulama yeniden başlatılırsa GET isteği herhangi bir veri döndürmez. Veri döndürülmezse, uygulamaya POST verileri gönderin ve GET isteğini yeniden deneyin.
Dönüş değerleri
ASP.NET Core, nesneyi otomatik olarak JSON'a serileştirir ve JSON'ı yanıt iletisinin gövdesine yazar. İşlenmeyen özel durum olmadığı varsayılarak, bu dönüş türünün yanıt kodu 200 Tamam'dır. İşlenmeyen özel durumlar 5xx hatalarına çevrilir.
Dönüş türleri çok çeşitli HTTP durum kodlarını temsil edebilir. Örneğin, GET /todoitems/{id}
iki farklı durum değeri döndürebilir:
- İstenen kimlikle eşleşen öğe yoksa, yöntem bir 404 durum NotFound hata kodu döndürür.
- Aksi takdirde, yöntemi bir JSON yanıt gövdesi ile 200 döndürür. Http 200 yanıtında sonuç döndürme
item
.
PUT uç noktasını inceleme
Örnek uygulama kullanarak MapPut
tek bir PUT uç noktası uygular:
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
Bu yöntem yöntemine MapPost
benzer, ancak HTTP PUT kullanır. Başarılı bir yanıt 204 (İçerik Yok) döndürür. HTTP belirtimine göre, PUT isteği istemcinin yalnızca değişiklikleri değil güncelleştirilmiş varlığın tamamını göndermesini gerektirir. Kısmi güncelleştirmeleri desteklemek için HTTP PATCH kullanın.
PUT uç noktasını test edin
Bu örnek, uygulama her başlatıldığında başlatılması gereken bir bellek içi veritabanı kullanır. PUT çağrısından önce veritabanında bir öğe olmalıdır. PUT çağrısı yapmadan önce veritabanında bir öğe olduğundan emin olmak için GET çağrısı yapın.
öğesini içeren ve adını "feed fish"
olarak ayarlayan Id = 1
yapılacaklar öğesini güncelleştirin.
PUT isteği göndermek için Swagger kullanın:
Koy /todoitems/{id}>Deneyin'i seçin.
Kimlik alanını olarak
1
ayarlayın.İstek gövdesini aşağıdaki JSON olarak ayarlayın:
{ "name": "feed fish", "isComplete": false }
Yürüt'ü seçin.
DELETE uç noktasını inceleme ve test edin
Örnek uygulama kullanarak MapDelete
tek bir DELETE uç noktası uygular:
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
DELETE isteği göndermek için Swagger'ı kullanın:
DELETE /todoitems/{id}>Deneyin'i seçin.
Kimlik alanını olarak
1
ayarlayın ve Yürüt'e tıklayın.DELETE isteği uygulamaya gönderilir ve yanıt Yanıtlar bölmesinde görüntülenir. Yanıt gövdesi boş ve Sunucu yanıt durumu kodu 204'dür.
Fazla deftere nakledilmesini engelle
Şu anda örnek uygulama tüm Todo
nesneyi kullanıma sunar. Üretim uygulamaları Üretim uygulamalarında, girişi ve döndürülebilecek verileri kısıtlamak için genellikle modelin bir alt kümesi kullanılır. Bunun arkasında birden çok neden vardır ve güvenlik önemli bir nedendir. Modelin alt kümesi genellikle Veri Aktarım Nesnesi (DTO), giriş modeli veya görünüm modeli olarak adlandırılır. DTO bu makalede kullanılmıştır.
DTO şu şekilde kullanılabilir:
- Fazla göndermeyi engelle.
- İstemcilerin görüntülememesi gereken özellikleri gizleyin.
- Yük boyutunu küçültmek için bazı özellikleri atlar.
- İç içe nesneler içeren nesne grafiklerini düzleştirme. Düzleştirilmiş nesne grafikleri istemciler için daha kullanışlı olabilir.
DTO yaklaşımını göstermek için sınıfını bir gizli dizi alanı içerecek şekilde güncelleştirin Todo
:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
Gizli dizi alanının bu uygulamadan gizlenmesi gerekir, ancak bir yönetim uygulaması bunu kullanıma sunma seçeneğini belirleyebilir.
Gizli dizi alanını gönderip alabildiğinizi doğrulayın.
Aşağıdaki kodla adlı TodoItemDTO.cs
bir dosya oluşturun:
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}
Bu DTO modelini kullanmak için dosyanın içeriğini Program.cs
aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
var app = builder.Build();
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.Select(x => new TodoItemDTO(x)).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(new TodoItemDTO(todo))
: Results.NotFound());
app.MapPost("/todoitems", async (TodoItemDTO todoItemDTO, TodoDb db) =>
{
var todoItem = new Todo
{
IsComplete = todoItemDTO.IsComplete,
Name = todoItemDTO.Name
};
db.Todos.Add(todoItem);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todoItem.Id}", new TodoItemDTO(todoItem));
});
app.MapPut("/todoitems/{id}", async (int id, TodoItemDTO todoItemDTO, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = todoItemDTO.Name;
todo.IsComplete = todoItemDTO.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Gizli dizi alanı dışındaki tüm alanları gönderip alabildiğinizi doğrulayın.
En düşük API'leri test edin
En düşük API uygulamasını test etme örneği için bu GitHub örneğine bakın.
Azure'a Yayımlama
Azure'a dağıtma hakkında bilgi için bkz . Hızlı Başlangıç: ASP.NET web uygulaması dağıtma.
Ek kaynaklar
Minimum API'ler, en az bağımlılıkla HTTP API'leri oluşturmak için tasarlanır. Bunlar, ASP.NET Core'da yalnızca en düşük dosyaları, özellikleri ve bağımlılıkları dahil etmek isteyen mikro hizmetler ve uygulamalar için idealdir.
Bu öğreticide, ASP.NET Core ile minimum API oluşturmanın temelleri öğretilir. ASP.NET Core'da API oluşturmanın bir diğer yaklaşımı da denetleyicileri kullanmaktır. En düşük API'ler ile denetleyici tabanlı API'ler arasında seçim yaparken yardım için bkz . API'lere genel bakış. Daha fazla özellik içeren denetleyicileri temel alan bir API projesi oluşturma öğreticisi için bkz. Web API'si oluşturma.
Genel bakış
Bu öğretici aşağıdaki API'yi oluşturur:
API | Açıklama | Request body | Yanıt gövdesi |
---|---|---|---|
GET /todoitems |
Tüm yapılacaklar öğelerini alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/complete |
Tamamlanmış yapılacaklar öğeleri alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/{id} |
Öğeyi kimliğine göre alma | Hiçbiri | Yapılacaklar öğesi |
POST /todoitems |
Yeni öğe ekleme | Yapılacaklar öğesi | Yapılacaklar öğesi |
PUT /todoitems/{id} |
Var olan bir öğeyi güncelleştirme | Yapılacaklar öğesi | Hiçbiri |
DELETE /todoitems/{id} |
Öğe silme | Hiçbiri | Hiçbiri |
Önkoşullar
Visual Studio 2022 ile ASP.NET ve web geliştirme iş yükü.
API projesi oluşturma
Visual Studio 2022'yi başlatın ve Yeni proje oluştur'u seçin.
Yeni proje oluştur iletişim kutusunda:
- Şablon ara arama kutusuna girin
Empty
. - ASP.NET Çekirdek Boş şablonunu seçin ve İleri'yi seçin.
- Şablon ara arama kutusuna girin
Projeye TodoApi adını verin ve İleri'yi seçin.
Ek bilgi iletişim kutusunda:
- .NET 8.0 (Uzun Vadeli Destek) seçeneğini belirleyin
- Üst düzey deyimleri kullanma seçeneğinin işaretini kaldırın
- Oluştur'u seçin
Kodu inceleme
Dosya Program.cs
aşağıdaki kodu içerir:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Yukarıdaki kod:
- Önceden yapılandırılmış varsayılanlarla bir WebApplicationBuilder ve WebApplication oluşturur.
- döndüren
Hello World!
bir HTTP GET uç noktası/
oluşturur:
Uygulamayı çalıştırma
Hata ayıklayıcı olmadan çalıştırmak için Ctrl+F5 tuşlarına basın.
Visual Studio aşağıdaki iletişim kutusunu görüntüler:
IIS Express SSL sertifikasına güveniyorsanız Evet'i seçin.
Aşağıdaki iletişim kutusu görüntülenir:
Geliştirme sertifikasına güvenmeyi kabul ediyorsanız Evet'i seçin.
Firefox tarayıcısına güvenme hakkında bilgi için bkz . Firefox SEC_ERROR_INADEQUATE_KEY_USAGE sertifika hatası.
Visual Studio web sunucusunu başlatır Kestrel ve bir tarayıcı penceresi açar.
Hello World!
tarayıcıda görüntülenir. Dosya çok Program.cs
az ama eksiksiz bir uygulama içeriyor.
Tarayıcı penceresini kapatın.
NuGet paketlerini ekleme
Bu öğreticide kullanılan veritabanı ve tanılamayı desteklemek için NuGet paketleri eklenmelidir.
- Araçlar menüsünde NuGet Paket Yöneticisi > Çözüm için NuGet Paketlerini Yönet'i seçin.
- Gözat sekmesini seçin.
- Arama kutusuna Microsoft.EntityFrameworkCore.InMemory yazın ve öğesini seçin
Microsoft.EntityFrameworkCore.InMemory
. - Sağ bölmede Proje onay kutusunu ve ardından Yükle'yi seçin.
- Paketi eklemek
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
için önceki yönergeleri izleyin.
Model ve veritabanı bağlam sınıfları
- Proje klasöründe aşağıdaki kodla adlı
Todo.cs
bir dosya oluşturun:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
Yukarıdaki kod bu uygulama için modeli oluşturur. Model, uygulamanın yönettiği verileri temsil eden bir sınıftır.
- Aşağıdaki kodla adlı
TodoDb.cs
bir dosya oluşturun:
using Microsoft.EntityFrameworkCore;
class TodoDb : DbContext
{
public TodoDb(DbContextOptions<TodoDb> options)
: base(options) { }
public DbSet<Todo> Todos => Set<Todo>();
}
Yukarıdaki kod, bir veri modeli için Entity Framework işlevselliğini koordine eden ana sınıf olan veritabanı bağlamını tanımlar. Bu sınıf sınıfından Microsoft.EntityFrameworkCore.DbContext türetilir.
API kodunu ekleme
Program.cs
dosyasının içeriğini aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Aşağıdaki vurgulanmış kod, veritabanı bağlamını bağımlılık ekleme (DI) kapsayıcısına ekler ve veritabanıyla ilgili özel durumların görüntülenmesini sağlar:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
DI kapsayıcısı, veritabanı bağlamı ve diğer hizmetlere erişim sağlar.
Bu öğreticide API'yi test etmek için Uç Nokta Gezgini ve .http dosyaları kullanılır.
Test deftere nakil verileri
içindeki aşağıdaki kod Program.cs
, bellek içi veritabanına veri ekleyen bir HTTP POST uç noktası /todoitems
oluşturur:
app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
Uygulamayı çalıştırma. Artık uç nokta olmadığından /
tarayıcı 404 hatası görüntüler.
POST uç noktası, uygulamaya veri eklemek için kullanılır.
Diğer Windows>Uç Noktalarını Görüntüle>Gezgini'ne tıklayın.
POST uç noktasına sağ tıklayın ve İstek oluştur'a tıklayın.
adlı
TodoApi.http
proje klasöründe, içeriği aşağıdaki örneğe benzer şekilde yeni bir dosya oluşturulur:@TodoApi_HostAddress = https://localhost:7031 Post {{TodoApi_HostAddress}}/todoitems ###
- İlk satır, tüm uç noktalar için kullanılan bir değişken oluşturur.
- Sonraki satır bir POST isteği tanımlar.
- Üçlü hashtag (
###
) satırı bir istek sınırlayıcısıdır: farklı bir istek için bundan sonra gelenler.
POST isteği için üst bilgiler ve bir gövde gerekir. İsteğin bu bölümlerini tanımlamak için POST istek satırının hemen arkasına aşağıdaki satırları ekleyin:
Content-Type: application/json { "name":"walk dog", "isComplete":true }
Yukarıdaki kod bir content-Type üst bilgisi ve JSON istek gövdesi ekler. TodoApi.http dosyası artık aşağıdaki örnekteki gibi görünmelidir, ancak bağlantı noktası numaranızla birlikte:
@TodoApi_HostAddress = https://localhost:7057 Post {{TodoApi_HostAddress}}/todoitems Content-Type: application/json { "name":"walk dog", "isComplete":true } ###
Uygulamayı çalıştırma.
İstek satırının üzerindeki
POST
İstek gönder bağlantısını seçin.POST isteği uygulamaya gönderilir ve yanıt Yanıt bölmesinde görüntülenir.
GET uç noktalarını inceleme
Örnek uygulama çağrısı MapGet
yaparak birkaç GET uç noktası uygular:
API | Açıklama | Request body | Yanıt gövdesi |
---|---|---|---|
GET /todoitems |
Tüm yapılacaklar öğelerini alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/complete |
Tüm tamamlanmış yapılacaklar öğelerini alma | Hiçbiri | Yapılacaklar öğeleri dizisi |
GET /todoitems/{id} |
Öğeyi kimliğine göre alma | Hiçbiri | Yapılacaklar öğesi |
app.MapGet("/todoitems", async (TodoDb db) =>
await db.Todos.ToListAsync());
app.MapGet("/todoitems/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
GET uç noktalarını test edin
Bir tarayıcıdan uç noktaları çağırarak GET
veya Uç Nokta Gezgini'ni kullanarak uygulamayı test edin. Aşağıdaki adımlar Uç Nokta Gezgini'ne yöneliktir.
Uç Nokta Gezgini'nde ilk GET uç noktasına sağ tıklayın ve İstek oluştur'a tıklayın.
Dosyaya
TodoApi.http
aşağıdaki içerik eklenir:Get {{TodoApi_HostAddress}}/todoitems ###
Yeni
GET
istek satırının üzerindeki İstek gönder bağlantısını seçin.GET isteği uygulamaya gönderilir ve yanıt Yanıt bölmesinde görüntülenir.
Yanıt gövdesi aşağıdaki JSON'a benzer:
[ { "id": 1, "name": "walk dog", "isComplete": true } ]
Uç Nokta Gezgini'nde GET uç noktasına sağ tıklayın
/todoitems/{id}
ve İstek oluştur'a tıklayın. DosyayaTodoApi.http
aşağıdaki içerik eklenir:GET {{TodoApi_HostAddress}}/todoitems/{id} ###
{id}
öğesini1
ile değiştirin.Yeni GET isteği satırının üzerindeki İstek gönder bağlantısını seçin.
GET isteği uygulamaya gönderilir ve yanıt Yanıt bölmesinde görüntülenir.
Yanıt gövdesi aşağıdaki JSON'a benzer:
{ "id": 1, "name": "walk dog", "isComplete": true }
Bu uygulama bellek içi veritabanı kullanıyor. Uygulama yeniden başlatılırsa GET isteği herhangi bir veri döndürmez. Veri döndürülmezse, uygulamaya POST verileri gönderin ve GET isteğini yeniden deneyin.
Dönüş değerleri
ASP.NET Core, nesneyi otomatik olarak JSON'a serileştirir ve JSON'ı yanıt iletisinin gövdesine yazar. İşlenmeyen özel durum olmadığı varsayılarak, bu dönüş türünün yanıt kodu 200 Tamam'dır. İşlenmeyen özel durumlar 5xx hatalarına çevrilir.
Dönüş türleri çok çeşitli HTTP durum kodlarını temsil edebilir. Örneğin, GET /todoitems/{id}
iki farklı durum değeri döndürebilir:
- İstenen kimlikle eşleşen öğe yoksa, yöntem bir 404 durum NotFound hata kodu döndürür.
- Aksi takdirde, yöntemi bir JSON yanıt gövdesi ile 200 döndürür. Http 200 yanıtında sonuç döndürme
item
.
PUT uç noktasını inceleme
Örnek uygulama kullanarak MapPut
tek bir PUT uç noktası uygular:
app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
Bu yöntem yöntemine MapPost
benzer, ancak HTTP PUT kullanır. Başarılı bir yanıt 204 (İçerik Yok) döndürür. HTTP belirtimine göre, PUT isteği istemcinin yalnızca değişiklikleri değil güncelleştirilmiş varlığın tamamını göndermesini gerektirir. Kısmi güncelleştirmeleri desteklemek için HTTP PATCH kullanın.
PUT uç noktasını test edin
Bu örnek, uygulama her başlatıldığında başlatılması gereken bir bellek içi veritabanı kullanır. PUT çağrısından önce veritabanında bir öğe olmalıdır. PUT çağrısı yapmadan önce veritabanında bir öğe olduğundan emin olmak için GET çağrısı yapın.
öğesini içeren ve adını "feed fish"
olarak ayarlayan Id = 1
yapılacaklar öğesini güncelleştirin.
Uç Nokta Gezgini'nde PUT uç noktasına sağ tıklayın ve İstek oluştur'a tıklayın.
Dosyaya
TodoApi.http
aşağıdaki içerik eklenir:Put {{TodoApi_HostAddress}}/todoitems/{id} ###
PUT istek satırında değerini ile
1
değiştirin{id}
.PUT istek satırının hemen arkasına aşağıdaki satırları ekleyin:
Content-Type: application/json { "name": "feed fish", "isComplete": false }
Yukarıdaki kod bir content-Type üst bilgisi ve JSON istek gövdesi ekler.
Yeni PUT istek satırının üzerindeki İstek gönder bağlantısını seçin.
PUT isteği uygulamaya gönderilir ve yanıt Yanıt bölmesinde görüntülenir. Yanıt gövdesi boş ve durum kodu 204'dür.
DELETE uç noktasını inceleme ve test edin
Örnek uygulama kullanarak MapDelete
tek bir DELETE uç noktası uygular:
app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
Uç Nokta Gezgini'nde DELETE uç noktasına sağ tıklayın ve İstek oluştur'a tıklayın.
öğesine bir DELETE isteği eklenir
TodoApi.http
.DELETE isteği satırında değerini ile
1
değiştirin{id}
. DELETE isteği aşağıdaki örnekteki gibi görünmelidir:DELETE {{TodoApi_HostAddress}}/todoitems/1 ###
DELETE isteği için İstek gönder bağlantısını seçin.
DELETE isteği uygulamaya gönderilir ve yanıt Yanıt bölmesinde görüntülenir. Yanıt gövdesi boş ve durum kodu 204'dür.
MapGroup API'sini kullanma
Örnek uygulama kodu, her uç nokta ayarlayışında todoitems
URL ön ekini yineler. API'ler genellikle ortak URL ön ekine sahip uç nokta gruplarına sahiptir ve MapGroup bu tür grupların düzenlenmesine yardımcı olmak için yöntemi kullanılabilir. Yinelenen kodu azaltır ve ve WithMetadatagibi RequireAuthorization yöntemlere tek bir çağrıyla tüm uç nokta gruplarını özelleştirmeye olanak tanır.
öğesinin içeriğini Program.cs
aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", async (TodoDb db) =>
await db.Todos.ToListAsync());
todoItems.MapGet("/complete", async (TodoDb db) =>
await db.Todos.Where(t => t.IsComplete).ToListAsync());
todoItems.MapGet("/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound());
todoItems.MapPost("/", async (Todo todo, TodoDb db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
});
todoItems.MapPut("/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return Results.NoContent();
});
todoItems.MapDelete("/{id}", async (int id, TodoDb db) =>
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
}
return Results.NotFound();
});
app.Run();
Yukarıdaki kodda aşağıdaki değişiklikler vardır:
- URL ön ekini
/todoitems
kullanarak grubu ayarlamaya eklervar todoItems = app.MapGroup("/todoitems");
. - Tüm
app.Map<HttpVerb>
yöntemleri olaraktodoItems.Map<HttpVerb>
değiştirir. - Url ön ekini
/todoitems
yöntem çağrılarındanMap<HttpVerb>
kaldırır.
Aynı şekilde çalıştıklarını doğrulamak için uç noktaları test edin.
TypedResults API'sini kullanma
Döndürmenin TypedResults , test edilebilirlik ve uç noktayı açıklamak üzere OpenAPI için yanıt türü meta verilerini otomatik olarak döndürme gibi çeşitli avantajları vardır Results . Daha fazla bilgi için bkz . TypedResults vs Results.
Yöntemler, Map<HttpVerb>
lambda kullanmak yerine yol işleyicisi yöntemlerini çağırabilir. Bir örneği görmek için Program.cs aşağıdaki kodla güncelleştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
app.Run();
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Kod Map<HttpVerb>
artık lambda yerine yöntemleri çağırır:
var todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
Bu yöntemler uygulayan IResult ve tarafından TypedResultstanımlanan nesneleri döndürür:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(Todo todo, TodoDb db)
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return TypedResults.Created($"/todoitems/{todo.Id}", todo);
}
static async Task<IResult> UpdateTodo(int id, Todo inputTodo, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = inputTodo.Name;
todo.IsComplete = inputTodo.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Birim testleri bu yöntemleri çağırabilir ve doğru türü döndürdüğünü test edebilir. Örneğin, yöntemi ise GetAllTodos
:
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.ToArrayAsync());
}
Birim test kodu, Ok<Todo[]> türünde bir nesnenin işleyici yönteminden döndürüldüğünü doğrulayabilir. Örneğin:
public async Task GetAllTodos_ReturnsOkOfTodosResult()
{
// Arrange
var db = CreateDbContext();
// Act
var result = await TodosApi.GetAllTodos(db);
// Assert: Check for the correct returned type
Assert.IsType<Ok<Todo[]>>(result);
}
Fazla deftere nakledilmesini engelle
Şu anda örnek uygulama tüm Todo
nesneyi kullanıma sunar. Üretim uygulamaları Üretim uygulamalarında, girişi ve döndürülebilecek verileri kısıtlamak için genellikle modelin bir alt kümesi kullanılır. Bunun arkasında birden çok neden vardır ve güvenlik önemli bir nedendir. Modelin alt kümesi genellikle Veri Aktarım Nesnesi (DTO), giriş modeli veya görünüm modeli olarak adlandırılır. DTO bu makalede kullanılmıştır.
DTO şu şekilde kullanılabilir:
- Fazla göndermeyi engelle.
- İstemcilerin görüntülememesi gereken özellikleri gizleyin.
- Yük boyutunu küçültmek için bazı özellikleri atlar.
- İç içe nesneler içeren nesne grafiklerini düzleştirme. Düzleştirilmiş nesne grafikleri istemciler için daha kullanışlı olabilir.
DTO yaklaşımını göstermek için sınıfını bir gizli dizi alanı içerecek şekilde güncelleştirin Todo
:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
Gizli dizi alanının bu uygulamadan gizlenmesi gerekir, ancak bir yönetim uygulaması bunu kullanıma sunma seçeneğini belirleyebilir.
Gizli dizi alanını gönderip alabildiğinizi doğrulayın.
Aşağıdaki kodla adlı TodoItemDTO.cs
bir dosya oluşturun:
public class TodoItemDTO
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public TodoItemDTO() { }
public TodoItemDTO(Todo todoItem) =>
(Id, Name, IsComplete) = (todoItem.Id, todoItem.Name, todoItem.IsComplete);
}
Bu DTO modelini kullanmak için dosyanın içeriğini Program.cs
aşağıdaki kodla değiştirin:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
var app = builder.Build();
RouteGroupBuilder todoItems = app.MapGroup("/todoitems");
todoItems.MapGet("/", GetAllTodos);
todoItems.MapGet("/complete", GetCompleteTodos);
todoItems.MapGet("/{id}", GetTodo);
todoItems.MapPost("/", CreateTodo);
todoItems.MapPut("/{id}", UpdateTodo);
todoItems.MapDelete("/{id}", DeleteTodo);
app.Run();
static async Task<IResult> GetAllTodos(TodoDb db)
{
return TypedResults.Ok(await db.Todos.Select(x => new TodoItemDTO(x)).ToArrayAsync());
}
static async Task<IResult> GetCompleteTodos(TodoDb db) {
return TypedResults.Ok(await db.Todos.Where(t => t.IsComplete).Select(x => new TodoItemDTO(x)).ToListAsync());
}
static async Task<IResult> GetTodo(int id, TodoDb db)
{
return await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(new TodoItemDTO(todo))
: TypedResults.NotFound();
}
static async Task<IResult> CreateTodo(TodoItemDTO todoItemDTO, TodoDb db)
{
var todoItem = new Todo
{
IsComplete = todoItemDTO.IsComplete,
Name = todoItemDTO.Name
};
db.Todos.Add(todoItem);
await db.SaveChangesAsync();
todoItemDTO = new TodoItemDTO(todoItem);
return TypedResults.Created($"/todoitems/{todoItem.Id}", todoItemDTO);
}
static async Task<IResult> UpdateTodo(int id, TodoItemDTO todoItemDTO, TodoDb db)
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return TypedResults.NotFound();
todo.Name = todoItemDTO.Name;
todo.IsComplete = todoItemDTO.IsComplete;
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
static async Task<IResult> DeleteTodo(int id, TodoDb db)
{
if (await db.Todos.FindAsync(id) is Todo todo)
{
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return TypedResults.NoContent();
}
return TypedResults.NotFound();
}
Gizli dizi alanı dışındaki tüm alanları gönderip alabildiğinizi doğrulayın.
Tamamlanan örnekle ilgili sorun giderme
Çözemediğiniz bir sorunla karşılaşırsanız kodunuzu tamamlanmış projeyle karşılaştırın. Tamamlanan projeyi görüntüleme veya indirme (indirme).
Sonraki adımlar
- JSON serileştirme seçeneklerini yapılandırın.
- Hataları ve özel durumları işleme: Geliştirici özel durum sayfası , minimum API uygulamaları için geliştirme ortamında varsayılan olarak etkindir. Hataları ve özel durumları işleme hakkında bilgi için bkz . ASP.NET Core API'lerindeki hataları işleme.
- En düşük API uygulamasını test etme örneği için bu GitHub örneğine bakın.
- Minimum API'lerde OpenAPI desteği.
- Hızlı Başlangıç: Azure'da yayımlama.
- ASP.NET Temel Minimum API'leri düzenleme.
Daha fazla bilgi edinin
ASP.NET Core