En az API hızlı başvurusu
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.
Bu belge:
- En düşük API'ler için hızlı başvuru sağlar.
- Deneyimli geliştiricilere yöneliktir. Giriş için bkz . Öğretici: ASP.NET Core ile minimum API oluşturma.
En düşük API'ler şunlardan oluşur:
WebApplication
Aşağıdaki kod bir ASP.NET Core şablonu tarafından oluşturulur:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Yukarıdaki kod, komut satırında veya Visual Studio'da Boş Web şablonu seçerek oluşturulabilir dotnet new web
.
Aşağıdaki kod, açıkça oluşturmadan bir WebApplication WebApplicationBuilder(app
) oluşturur:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create
önceden yapılandırılmış varsayılanlarla sınıfının yeni bir örneğini WebApplication başlatır.
WebApplication
aşağıdaki ara yazılımı Minimal API applications
belirli koşullara bağlı olarak otomatik olarak ekler:
UseDeveloperExceptionPage
, olduğundaHostingEnvironment
"Development"
ilk olarak eklenir.UseRouting
, kullanıcı kodu henüz çağrılmazsaUseRouting
ve örneğinapp.MapGet
yapılandırılmış uç noktalar varsa eklenir.UseEndpoints
, herhangi bir uç nokta yapılandırılırsa ara yazılım işlem hattının sonuna eklenir.UseAuthentication
kullanıcı kodu henüz çağrılmazsaUseAuthentication
ve hizmet sağlayıcısında algılanabilirseIAuthenticationSchemeProvider
hemen sonraUseRouting
eklenir.IAuthenticationSchemeProvider
kullanılırkenAddAuthentication
varsayılan olarak eklenir ve kullanılarak hizmetler algılanırIServiceProviderIsService
.UseAuthorization
, kullanıcı kodu henüz çağrılmazsaUseAuthorization
ve hizmet sağlayıcısında algılanabilirseIAuthorizationHandlerProvider
eklenir.IAuthorizationHandlerProvider
kullanılırkenAddAuthorization
varsayılan olarak eklenir ve kullanılarak hizmetler algılanırIServiceProviderIsService
.- Kullanıcı tarafından yapılandırılmış ara yazılım ve uç noktalar ile
UseEndpoints
arasınaUseRouting
eklenir.
Aşağıdaki kod, uygulamaya eklenen otomatik ara yazılımların etkili bir şekilde ürettiği koddur:
if (isDevelopment)
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
if (isAuthenticationConfigured)
{
app.UseAuthentication();
}
if (isAuthorizationConfigured)
{
app.UseAuthorization();
}
// user middleware/endpoints
app.CustomMiddleware(...);
app.MapGet("/", () => "hello world");
// end user middleware/endpoints
app.UseEndpoints(e => {});
Bazı durumlarda, varsayılan ara yazılım yapılandırması uygulama için doğru değildir ve değişiklik gerektirir. Örneğin, UseCors ve UseAuthorizationöncesinde UseAuthentication çağrılmalıdır. Uygulamanın çağrısı UseAuthentication
UseAuthorization
ve çağrılıp çağrılmaması UseCors
gerekir:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Yol eşleştirme gerçekleşmeden önce ara yazılım çalıştırılmalıdır, UseRouting çağrılmalı ve ara yazılım çağrısından UseRouting
önce yerleştirilmelidir. UseEndpoints daha önce açıklandığı gibi otomatik olarak eklendiğinden bu durumda gerekli değildir:
app.Use((context, next) =>
{
return next(context);
});
app.UseRouting();
// other middleware and endpoints
Terminal ara yazılımı eklerken:
- Ara yazılım, sonrasında
UseEndpoints
eklenmelidir. - Terminal ara yazılımının doğru konuma yerleştirilebilmesi için uygulamanın araması
UseRouting
UseEndpoints
gerekir.
app.UseRouting();
app.MapGet("/", () => "hello world");
app.UseEndpoints(e => {});
app.Run(context =>
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
Terminal ara yazılımı, isteği hiçbir uç nokta işlemezse çalışan ara yazılımdır.
Bağlantı noktalarıyla çalışma
Visual Studio veya dotnet new
ile bir web uygulaması oluşturulduğunda, uygulamanın yanıt verdiği bağlantı noktalarını belirten bir Properties/launchSettings.json
dosya oluşturulur. Sonraki bağlantı noktası ayarı örneklerinde, uygulamayı Visual Studio'dan çalıştırmak bir hata iletişim kutusu Unable to connect to web server 'AppName'
döndürür. Visual Studio, içinde Properties/launchSettings.json
belirtilen bağlantı noktasını beklediğinden ancak uygulama tarafından app.Run("http://localhost:3000")
belirtilen bağlantı noktasını kullandığından bir hata döndürür. Komut satırından örnekleri değiştirerek aşağıdaki bağlantı noktasını çalıştırın.
Aşağıdaki bölümlerde uygulamanın yanıt verdiği bağlantı noktası ayarlanır.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
Önceki kodda uygulama bağlantı noktasına 3000
yanıt verir.
Birden çok bağlantı noktası
Aşağıdaki kodda uygulama ve 4000
bağlantı noktasına 3000
yanıt verir.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
Komut satırından bağlantı noktasını ayarlama
Aşağıdaki komut, uygulamanın bağlantı noktasına 7777
yanıt vermesini sağlar:
dotnet run --urls="https://localhost:7777"
Kestrel Uç nokta dosyada appsettings.json
da yapılandırılmışsa, appsettings.json
belirtilen dosya URL'si kullanılır. Daha fazla bilgi için bkz. Kestrel uç nokta yapılandırması
Bağlantı noktasını ortamdan okuma
Aşağıdaki kod, bağlantı noktasını ortamdan okur:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
Bağlantı noktasını ortamdan ayarlamanın tercih edilen yolu, aşağıdaki bölümde gösterilen ortam değişkenini kullanmaktır ASPNETCORE_URLS
.
ASPNETCORE_URLS ortam değişkeni aracılığıyla bağlantı noktalarını ayarlama
Ortam ASPNETCORE_URLS
değişkeni, bağlantı noktasını ayarlamak için kullanılabilir:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS
birden çok URL'leri destekler:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
Tüm arabirimlerde dinleme
Aşağıdaki örneklerde tüm arabirimlerde dinleme gösterilmektedir
http://*:3000
var app = WebApplication.Create(args);
app.Urls.Add("http://*:3000");
app.MapGet("/", () => "Hello World");
app.Run();
http://+:3000
var app = WebApplication.Create(args);
app.Urls.Add("http://+:3000");
app.MapGet("/", () => "Hello World");
app.Run();
http://0.0.0.0:3000
var app = WebApplication.Create(args);
app.Urls.Add("http://0.0.0.0:3000");
app.MapGet("/", () => "Hello World");
app.Run();
ASPNETCORE_URLS kullanarak tüm arabirimlerde dinleme
Önceki örnekler kullanabilir ASPNETCORE_URLS
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
ASPNETCORE_HTTPS_PORTS kullanarak tüm arabirimleri dinleme
Yukarıdaki örnekler ve ASPNETCORE_HTTP_PORTS
kullanabilirASPNETCORE_HTTPS_PORTS
.
ASPNETCORE_HTTP_PORTS=3000;5005
ASPNETCORE_HTTPS_PORTS=5000
Daha fazla bilgi için bkz . ASP.NET Core Kestrel web sunucusu için uç noktaları yapılandırma
Geliştirme sertifikası ile HTTPS belirtme
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Geliştirme sertifikası hakkında daha fazla bilgi için bkz . Windows ve macOS'ta ASP.NET Core HTTPS geliştirme sertifikasına güvenme.
Özel sertifika kullanarak HTTPS belirtme
Aşağıdaki bölümlerde, dosyayı kullanarak ve yapılandırma yoluyla özel sertifikanın nasıl belirtileceğini gösterilmektedir appsettings.json
.
Ile özel sertifikayı belirtin appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Yapılandırma aracılığıyla özel sertifikayı belirtme
var builder = WebApplication.CreateBuilder(args);
// Configure the cert and the key
builder.Configuration["Kestrel:Certificates:Default:Path"] = "cert.pem";
builder.Configuration["Kestrel:Certificates:Default:KeyPath"] = "key.pem";
var app = builder.Build();
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Sertifika API'lerini kullanma
using System.Security.Cryptography.X509Certificates;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
options.ConfigureHttpsDefaults(httpsOptions =>
{
var certPath = Path.Combine(builder.Environment.ContentRootPath, "cert.pem");
var keyPath = Path.Combine(builder.Environment.ContentRootPath, "key.pem");
httpsOptions.ServerCertificate = X509Certificate2.CreateFromPemFile(certPath,
keyPath);
});
});
var app = builder.Build();
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Ortamı okuma
var app = WebApplication.Create(args);
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/oops");
}
app.MapGet("/", () => "Hello World");
app.MapGet("/oops", () => "Oops! An error happened.");
app.Run();
Ortamı kullanma hakkında daha fazla bilgi için bkz . ASP.NET Core'da birden çok ortam kullanma
Yapılandırma
Aşağıdaki kod yapılandırma sisteminden okunur:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Config failed!";
app.MapGet("/", () => message);
app.Run();
Daha fazla bilgi için bkz . ASP.NET Core'da yapılandırma
Günlük Kaydı
Aşağıdaki kod, oturum açma uygulaması başlatma işlemine bir ileti yazar:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
Daha fazla bilgi için bkz . .NET Core ve ASP.NET Core'da oturum açma
Bağımlılık Ekleme (DI) kapsayıcıya erişme
Aşağıdaki kod, uygulama başlatma sırasında DI kapsayıcısından hizmet almayı gösterir:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddScoped<SampleService>();
var app = builder.Build();
app.MapControllers();
using (var scope = app.Services.CreateScope())
{
var sampleService = scope.ServiceProvider.GetRequiredService<SampleService>();
sampleService.DoSomething();
}
app.Run();
Aşağıdaki kod, özniteliğini kullanarak DI kapsayıcısından anahtarlara erişmeyi [FromKeyedServices]
gösterir:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");
var app = builder.Build();
app.MapGet("/big", ([FromKeyedServices("big")] ICache bigCache) => bigCache.Get("date"));
app.MapGet("/small", ([FromKeyedServices("small")] ICache smallCache) => smallCache.Get("date"));
app.Run();
public interface ICache
{
object Get(string key);
}
public class BigCache : ICache
{
public object Get(string key) => $"Resolving {key} from big cache.";
}
public class SmallCache : ICache
{
public object Get(string key) => $"Resolving {key} from small cache.";
}
DI hakkında daha fazla bilgi için bkz . ASP.NET Core'da bağımlılık ekleme.
WebApplicationBuilder
Bu bölüm, kullanan WebApplicationBuilderörnek kodu içerir.
İçerik kökünü, uygulama adını ve ortamı değiştirme
Aşağıdaki kod içerik kökünü, uygulama adını ve ortamı ayarlar:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
ApplicationName = typeof(Program).Assembly.FullName,
ContentRootPath = Directory.GetCurrentDirectory(),
EnvironmentName = Environments.Staging,
WebRootPath = "customwwwroot"
});
Console.WriteLine($"Application Name: {builder.Environment.ApplicationName}");
Console.WriteLine($"Environment Name: {builder.Environment.EnvironmentName}");
Console.WriteLine($"ContentRoot Path: {builder.Environment.ContentRootPath}");
Console.WriteLine($"WebRootPath: {builder.Environment.WebRootPath}");
var app = builder.Build();
WebApplication.CreateBuilder önceden yapılandırılmış varsayılanlarla WebApplicationBuilder sınıfının yeni bir örneğini başlatır.
Daha fazla bilgi için bkz . ASP.NET Temel bilgilere genel bakış
Ortam değişkenlerini veya komut satırını kullanarak içerik kökünü, uygulama adını ve ortamı değiştirme
Aşağıdaki tabloda içerik kökünü, uygulama adını ve ortamı değiştirmek için kullanılan ortam değişkeni ve komut satırı bağımsız değişkeni gösterilmektedir:
özelliği | Ortam değişkeni | Komut satırı bağımsız değişkeni |
---|---|---|
Uygulama adı | ASPNETCORE_APPLICATIONNAME | --applicationName |
Ortam adı | ASPNETCORE_ENVIRONMENT | --çevre |
İçerik kökü | ASPNETCORE_CONTENTROOT | --contentRoot |
Yapılandırma sağlayıcıları ekleme
Aşağıdaki örnek INI yapılandırma sağlayıcısını ekler:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Ayrıntılı bilgi için bkz. ASP.NET Core'da Yapılandırma bölümünde dosya yapılandırma sağlayıcıları.
Yapılandırmayı okuma
Varsayılan olarak WebApplicationBuilder , yapılandırmayı aşağıdakiler dahil olmak üzere birden çok kaynaktan okur:
appSettings.json
veappSettings.{environment}.json
- Ortam değişkenleri
- Komut satırı
Yapılandırma kaynaklarının tam listesi için bkz. ASP.NET Core'da Yapılandırma'da varsayılan yapılandırma.
Aşağıdaki kod yapılandırmadan okur HelloKey
ve değeri uç noktada görüntüler /
. Yapılandırma değeri null ise , "Hello" öğesine message
atanır:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
Ortamı okuma
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsDevelopment())
{
Console.WriteLine($"Running in development.");
}
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Günlük sağlayıcıları ekleme
var builder = WebApplication.CreateBuilder(args);
// Configure JSON logging to the console.
builder.Logging.AddJsonConsole();
var app = builder.Build();
app.MapGet("/", () => "Hello JSON console!");
app.Run();
Hizmet ekleme
var builder = WebApplication.CreateBuilder(args);
// Add the memory cache services.
builder.Services.AddMemoryCache();
// Add a custom scoped service.
builder.Services.AddScoped<ITodoRepository, TodoRepository>();
var app = builder.Build();
IHostBuilder'i özelleştirme
üzerindeki IHostBuilder mevcut uzantı yöntemlerine Host özelliği kullanılarak erişilebilir:
var builder = WebApplication.CreateBuilder(args);
// Wait 30 seconds for graceful shutdown.
builder.Host.ConfigureHostOptions(o => o.ShutdownTimeout = TimeSpan.FromSeconds(30));
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
IWebHostBuilder'i özelleştirme
üzerindeki IWebHostBuilder uzantı yöntemlerine WebApplicationBuilder.WebHost özelliği kullanılarak erişilebilir.
var builder = WebApplication.CreateBuilder(args);
// Change the HTTP server implemenation to be HTTP.sys based
builder.WebHost.UseHttpSys();
var app = builder.Build();
app.MapGet("/", () => "Hello HTTP.sys");
app.Run();
Web kökünü değiştirme
Varsayılan olarak, web kökü klasördeki içerik köküne wwwroot
göredir. Web kökü, statik dosyalar ara yazılımının statik dosyaları ara yazılımının ara yazılım tarafından arandığı yerdir. Web kökü ile, komut satırıyla WebHostOptions
veya yöntemiyle UseWebRoot değiştirilebilir:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Özel bağımlılık ekleme (DI) kapsayıcısı
Aşağıdaki örnekte Autofac kullanılır:
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
// Register services directly with Autofac here. Don't
// call builder.Populate(), that happens in AutofacServiceProviderFactory.
builder.Host.ConfigureContainer<ContainerBuilder>(builder => builder.RegisterModule(new MyApplicationModule()));
var app = builder.Build();
Ara Yazılım Ekle
Mevcut ASP.NET Core ara yazılımları üzerinde WebApplication
yapılandırılabilir:
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
Daha fazla bilgi için bkz . ASP.NET Core Ara Yazılımı
Geliştirici özel durum sayfası
WebApplication.CreateBuilder önceden yapılandırılmış varsayılanlarla sınıfının yeni bir örneğini WebApplicationBuilder başlatır. Geliştirici özel durum sayfası önceden yapılandırılmış varsayılanlarda etkinleştirilir. Geliştirme ortamında aşağıdaki kod çalıştırıldığında, öğesine /
gitmek özel durumu gösteren kolay bir sayfa oluşturur.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () =>
{
throw new InvalidOperationException("Oops, the '/' route has thrown an exception.");
});
app.Run();
ASP.NET Core Ara Yazılımı
Aşağıdaki tabloda en az API ile sık kullanılan ara yazılımlardan bazıları listelanmaktadır.
Ara yazılım | Açıklama | API |
---|---|---|
Kimlik Doğrulaması | Kimlik doğrulaması desteği sağlar. | UseAuthentication |
Yetkilendirme | Yetkilendirme desteği sağlar. | UseAuthorization |
CORS | Çıkış Noktaları Arası Kaynak Paylaşımı'nı yapılandırır. | UseCors |
Özel Durum İşleyicisi | Ara yazılım işlem hattı tarafından oluşan özel durumları genel olarak işler. | UseExceptionHandler |
İletilen Üst Bilgiler | Taşınan üst bilgileri geçerli isteğe iletir. | UseForwardedHeaders |
HTTPS Yeniden Yönlendirme | Tüm HTTP isteklerini HTTPS'ye yönlendirir. | UseHttpsRedirection |
HTTP Katı Aktarım Güvenliği (HSTS) | Özel bir yanıt üst bilgisi ekleyen güvenlik iyileştirme ara yazılımı. | UseHsts |
İstek Günlüğü | HTTP isteklerini ve yanıtlarını günlüğe kaydetme desteği sağlar. | UseHttpLogging |
İstek Zaman Aşımları | İstek zaman aşımlarını, genel varsayılan ve uç nokta başına yapılandırma desteği sağlar. | UseRequestTimeouts |
W3C İstek Günlüğü | HTTP isteklerini ve yanıtlarını W3C biçiminde günlüğe kaydetme desteği sağlar. | UseW3CLogging |
Yanıtları Önbelleğe Alma | Yanıtları önbelleğe almak için destek sağlar. | UseResponseCaching |
Yanıt Sıkıştırma | Yanıtları sıkıştırma desteği sağlar. | UseResponseCompression |
Oturum | Kullanıcı oturumlarını yönetmek için destek sağlar. | UseSession |
Statik Dosyalar | Statik dosyalara ve dizine göz atma desteği sağlar. | UseStaticFiles, UseFileServer |
WebSockets | WebSockets protokolünü etkinleştirir. | UseWebSockets |
Aşağıdaki bölümler istek işlemeyi kapsar: yönlendirme, parametre bağlama ve yanıtlar.
Yönlendirme
Yapılandırılmış WebApplication
bir , veya Delete
gibi Get
Post
Put
bir deve büyük/küçük harfli HTTP yöntemini destekler Map{Verb}
ve MapMethods buradadır:{Verb}
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "This is a GET");
app.MapPost("/", () => "This is a POST");
app.MapPut("/", () => "This is a PUT");
app.MapDelete("/", () => "This is a DELETE");
app.MapMethods("/options-or-head", new[] { "OPTIONS", "HEAD" },
() => "This is an options or head request ");
app.Run();
Delegate Bu yöntemlere geçirilen bağımsız değişkenler "yol işleyicileri" olarak adlandırılır.
Yol İşleyicileri
Yol işleyicileri, yol eşleştiğinde yürütülen yöntemlerdir. Yol işleyicileri bir lambda ifadesi, yerel bir işlev, örnek yöntemi veya statik bir yöntem olabilir. Yol işleyicileri zaman uyumlu veya zaman uyumsuz olabilir.
Lambda ifadesi
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/inline", () => "This is an inline lambda");
var handler = () => "This is a lambda variable";
app.MapGet("/", handler);
app.Run();
Yerel işlev
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Örnek yöntemi
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var handler = new HelloHandler();
app.MapGet("/", handler.Hello);
app.Run();
class HelloHandler
{
public string Hello()
{
return "Hello Instance method";
}
}
Statik yöntem
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", HelloHandler.Hello);
app.Run();
class HelloHandler
{
public static string Hello()
{
return "Hello static method";
}
}
Uç noktanın dışında tanımlanmış Program.cs
En az API'nin içinde Program.cs
bulunması gerekmez.
Program.cs
using MinAPISeparateFile;
var builder = WebApplication.CreateSlimBuilder(args);
var app = builder.Build();
TodoEndpoints.Map(app);
app.Run();
TodoEndpoints.cs
namespace MinAPISeparateFile;
public static class TodoEndpoints
{
public static void Map(WebApplication app)
{
app.MapGet("/", async context =>
{
// Get all todo items
await context.Response.WriteAsJsonAsync(new { Message = "All todo items" });
});
app.MapGet("/{id}", async context =>
{
// Get one todo item
await context.Response.WriteAsJsonAsync(new { Message = "One todo item" });
});
}
}
Ayrıca bu makalenin devamında Grupları yönlendirme bölümüne bakın.
Adlandırılmış uç noktalar ve bağlantı oluşturma
Uç noktaya URL'ler oluşturmak için uç noktalara adlar verilebilir. Adlandırılmış uç nokta kullanmak, bir uygulamada yolları sabit kodlamaktan kaçınıyor:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/hello", () => "Hello named route")
.WithName("hi");
app.MapGet("/", (LinkGenerator linker) =>
$"The link to the hello route is {linker.GetPathByName("hi", values: null)}");
app.Run();
Yukarıdaki kod uç noktadan görüntülenir The link to the hello route is /hello
/
.
NOT: Uç nokta adları büyük/küçük harfe duyarlıdır.
Uç nokta adları:
- Genel olarak benzersiz olması gerekir.
- OpenAPI desteği etkinleştirildiğinde OpenAPI işlem kimliği olarak kullanılır. Daha fazla bilgi için bkz . OpenAPI.
Rota Parametreleri
Yol parametreleri, yol deseni tanımının bir parçası olarak yakalanabilir:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/users/{userId}/books/{bookId}",
(int userId, int bookId) => $"The user id is {userId} and book id is {bookId}");
app.Run();
Yukarıdaki kod URI'sinden /users/3/books/7
döndürürThe user id is 3 and book id is 7
.
Yol işleyicisi, yakalanacak parametreleri bildirebilir. Yakalamak üzere bildirilen parametrelerle bir yola istek yapıldığında, parametreler ayrıştırılır ve işleyiciye geçirilir. Bu, değerleri güvenli bir şekilde tür olarak yakalamayı kolaylaştırır. Önceki kodda userId
ve bookId
her ikisi de int
şeklindedir.
Yukarıdaki kodda, herhangi bir yol değeri bir int
'a dönüştürülemezse bir özel durum oluşturulur. GET isteği /users/hello/books/3
aşağıdaki özel durumu oluşturur:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Joker karakter ve tüm yolları yakalama
Aşağıdaki catch all route returns Routing to hello
from the '/posts/hello' endpoint:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Yol kısıtlamaları
Yol kısıtlamaları, bir yolun eşleşen davranışını kısıtlar.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/todos/{id:int}", (int id) => db.Todos.Find(id));
app.MapGet("/todos/{text}", (string text) => db.Todos.Where(t => t.Text.Contains(text));
app.MapGet("/posts/{slug:regex(^[a-z0-9_-]+$)}", (string slug) => $"Post {slug}");
app.Run();
Aşağıdaki tabloda, önceki yol şablonları ve bunların davranışları gösterilmektedir:
Rota Şablonu | Örnek Eşleşen URI |
---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
Daha fazla bilgi için bkz. ASP.NET Core'da Yönlendirme bölümünde yönlendirme kısıtlaması başvurusu.
Yol grupları
Uzantı yöntemi, MapGroup ortak bir ön eke sahip uç nokta gruplarını düzenlemeye yardımcı olur. Yinelenen kodu azaltır ve uç nokta meta verilerini ekleyen ve WithMetadata gibi RequireAuthorization yöntemlere tek bir çağrıyla tüm uç nokta gruplarını özelleştirmeye olanak tanır.
Örneğin, aşağıdaki kod iki benzer uç nokta grubu oluşturur:
app.MapGroup("/public/todos")
.MapTodosApi()
.WithTags("Public");
app.MapGroup("/private/todos")
.MapTodosApi()
.WithTags("Private")
.AddEndpointFilterFactory(QueryPrivateTodos)
.RequireAuthorization();
EndpointFilterDelegate QueryPrivateTodos(EndpointFilterFactoryContext factoryContext, EndpointFilterDelegate next)
{
var dbContextIndex = -1;
foreach (var argument in factoryContext.MethodInfo.GetParameters())
{
if (argument.ParameterType == typeof(TodoDb))
{
dbContextIndex = argument.Position;
break;
}
}
// Skip filter if the method doesn't have a TodoDb parameter.
if (dbContextIndex < 0)
{
return next;
}
return async invocationContext =>
{
var dbContext = invocationContext.GetArgument<TodoDb>(dbContextIndex);
dbContext.IsPrivate = true;
try
{
return await next(invocationContext);
}
finally
{
// This should only be relevant if you're pooling or otherwise reusing the DbContext instance.
dbContext.IsPrivate = false;
}
};
}
public static RouteGroupBuilder MapTodosApi(this RouteGroupBuilder group)
{
group.MapGet("/", GetAllTodos);
group.MapGet("/{id}", GetTodo);
group.MapPost("/", CreateTodo);
group.MapPut("/{id}", UpdateTodo);
group.MapDelete("/{id}", DeleteTodo);
return group;
}
Bu senaryoda, sonuçta üst bilgi 201 Created
için Location
göreli bir adres kullanabilirsiniz:
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
İlk uç nokta grubu yalnızca ön ekli /public/todos
isteklerle eşleşir ve kimlik doğrulaması olmadan erişilebilir. İkinci uç nokta grubu yalnızca ön ekli isteklerle /private/todos
eşleşir ve kimlik doğrulaması gerektirir.
QueryPrivateTodos
Uç nokta filtresi fabrikası, özel todo verilerine erişmeye ve bunları depolamaya izin vermek için yol işleyicisinin TodoDb
parametrelerini değiştiren yerel bir işlevdir.
Yol grupları, yol parametreleri ve kısıtlamalarıyla iç içe grupları ve karmaşık ön ek desenlerini de destekler. Aşağıdaki örnekte, gruba eşlenen user
ve yol işleyicisi dış grup ön eklerinde tanımlanan ve {group}
yol parametrelerini yakalayabilir{org}
.
Ön ek de boş olabilir. Bu, yol desenini değiştirmeden bir uç nokta grubuna uç nokta meta verileri veya filtreleri eklemek için yararlı olabilir.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
Bir gruba filtre veya meta veri eklemek, bir iç gruba veya belirli bir uç noktaya eklenmiş olabilecek ek filtreler veya meta veriler eklemeden önce bunları her uç noktaya tek tek eklemekle aynı şekilde davranır.
var outer = app.MapGroup("/outer");
var inner = outer.MapGroup("/inner");
inner.AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("/inner group filter");
return next(context);
});
outer.AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("/outer group filter");
return next(context);
});
inner.MapGet("/", () => "Hi!").AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("MapGet filter");
return next(context);
});
Yukarıdaki örnekte dış filtre, ikinci kez eklenmiş olsa bile gelen isteği iç filtreden önce günlüğe kaydeder. Filtreler farklı gruplara uygulandığından, birbirlerine göre eklendikleri sıra önemli değildir. Sipariş filtrelerinin eklenmesi, aynı gruba veya belirli bir uç noktaya uygulandığında önemlidir.
için bir istek /outer/inner/
aşağıdakileri günlüğe kaydeder:
/outer group filter
/inner group filter
MapGet filter
Parametre bağlama
Parametre bağlama, istek verilerini yol işleyicileri tarafından ifade edilen kesin olarak belirlenmiş parametrelere dönüştürme işlemidir. Bağlama kaynağı, parametrelerin nereye bağlandığını belirler. Bağlama kaynakları HTTP yöntemine ve parametre türüne göre açık veya çıkarılabilir.
Desteklenen bağlama kaynakları:
- Yol değerleri
- Sorgu dizesi
- Üst bilgi
- Gövde (JSON olarak)
- Form değerleri
- Bağımlılık ekleme tarafından sağlanan hizmetler
- Özel
Aşağıdaki GET
yol işleyicisi bu parametre bağlama kaynaklarından bazılarını kullanır:
var builder = WebApplication.CreateBuilder(args);
// Added as service
builder.Services.AddSingleton<Service>();
var app = builder.Build();
app.MapGet("/{id}", (int id,
int page,
[FromHeader(Name = "X-CUSTOM-HEADER")] string customHeader,
Service service) => { });
class Service { }
Aşağıdaki tabloda, önceki örnekte kullanılan parametrelerle ilişkili bağlama kaynakları arasındaki ilişki gösterilmektedir.
Parametre | Bağlama Kaynağı |
---|---|
id |
yol değeri |
page |
sorgu dizesi |
customHeader |
üst bilgi |
service |
Bağımlılık ekleme tarafından sağlanır |
, , HEAD
OPTIONS
ve DELETE
HTTP yöntemleri GET
gövdeden örtük olarak bağlanmaz. Bu HTTP yöntemleri için gövdeden (JSON olarak) bağlanmak için ile [FromBody]
açıkça bağlayın veya dosyasından HttpRequestokuyun.
Aşağıdaki örnek POST yol işleyicisi, parametresi için person
bir bağlama gövdesi kaynağı (JSON olarak) kullanır:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/", (Person person) => { });
record Person(string Name, int Age);
Yukarıdaki örneklerde yer alan parametrelerin tümü istek verilerinden otomatik olarak bağlıdır. Parametre bağlamanın sağladığı kolaylığı göstermek için aşağıdaki yol işleyicileri istek verilerini doğrudan istekten nasıl okuyacaklarını gösterir:
app.MapGet("/{id}", (HttpRequest request) =>
{
var id = request.RouteValues["id"];
var page = request.Query["page"];
var customHeader = request.Headers["X-CUSTOM-HEADER"];
// ...
});
app.MapPost("/", async (HttpRequest request) =>
{
var person = await request.ReadFromJsonAsync<Person>();
// ...
});
Açık Parametre Bağlama
Öznitelikler, parametrelerin nereye bağlı olduğunu açıkça bildirmek için kullanılabilir.
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
// Added as service
builder.Services.AddSingleton<Service>();
var app = builder.Build();
app.MapGet("/{id}", ([FromRoute] int id,
[FromQuery(Name = "p")] int page,
[FromServices] Service service,
[FromHeader(Name = "Content-Type")] string contentType)
=> {});
class Service { }
record Person(string Name, int Age);
Parametre | Bağlama Kaynağı |
---|---|
id |
adıyla yol değeri id |
page |
adlı sorgu dizesi "p" |
service |
Bağımlılık ekleme tarafından sağlanır |
contentType |
adıyla üst bilgi "Content-Type" |
Form değerlerinden açık bağlama
[FromForm]
özniteliği form değerlerini bağlar:
app.MapPost("/todos", async ([FromForm] string name,
[FromForm] Visibility visibility, IFormFile? attachment, TodoDb db) =>
{
var todo = new Todo
{
Name = name,
Visibility = visibility
};
if (attachment is not null)
{
var attachmentName = Path.GetRandomFileName();
using var stream = File.Create(Path.Combine("wwwroot", attachmentName));
await attachment.CopyToAsync(stream);
}
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Ok();
});
// Remaining code removed for brevity.
Bunun alternatifi, özniteliğini [AsParameters]
ile ek açıklamalı özelliklere sahip özel bir türle kullanmaktır [FromForm]
. Örneğin, aşağıdaki kod form değerlerinden kayıt yapısının özelliklerine NewTodoRequest
bağlanır:
app.MapPost("/ap/todos", async ([AsParameters] NewTodoRequest request, TodoDb db) =>
{
var todo = new Todo
{
Name = request.Name,
Visibility = request.Visibility
};
if (request.Attachment is not null)
{
var attachmentName = Path.GetRandomFileName();
using var stream = File.Create(Path.Combine("wwwroot", attachmentName));
await request.Attachment.CopyToAsync(stream);
todo.Attachment = attachmentName;
}
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Ok();
});
// Remaining code removed for brevity.
public record struct NewTodoRequest([FromForm] string Name,
[FromForm] Visibility Visibility, IFormFile? Attachment);
Daha fazla bilgi için bu makalenin devamında yer alan AsParameters bölümüne bakın.
Örnek kodun tamamı AspNetCore.Docs.Samples deposundadır.
IFormFile ve IFormFileCollection'dan güvenli bağlama
Karmaşık form bağlama, kullanılarak IFormFile ve IFormFileCollection kullanılarak [FromForm]
desteklenir:
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder();
builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseAntiforgery();
// Generate a form with an anti-forgery token and an /upload endpoint.
app.MapGet("/", (HttpContext context, IAntiforgery antiforgery) =>
{
var token = antiforgery.GetAndStoreTokens(context);
var html = MyUtils.GenerateHtmlForm(token.FormFieldName, token.RequestToken!);
return Results.Content(html, "text/html");
});
app.MapPost("/upload", async Task<Results<Ok<string>, BadRequest<string>>>
([FromForm] FileUploadForm fileUploadForm, HttpContext context,
IAntiforgery antiforgery) =>
{
await MyUtils.SaveFileWithName(fileUploadForm.FileDocument!,
fileUploadForm.Name!, app.Environment.ContentRootPath);
return TypedResults.Ok($"Your file with the description:" +
$" {fileUploadForm.Description} has been uploaded successfully");
});
app.Run();
ile [FromForm]
isteğe bağlı parametreler, bir sahte belirteç içerir. İstek işlendiğinde, kötü amaçlı yazılımdan koruma belirteci doğrulanır. Daha fazla bilgi için bkz . Minimal API'lerle sahteciliğe karşı koruma.
Daha fazla bilgi için bkz. Minimum API'lerde form bağlama.
Örnek kodun tamamı AspNetCore.Docs.Samples deposundadır.
Bağımlılık ekleme ile parametre bağlama
En düşük API'ler için parametre bağlama, tür hizmet olarak yapılandırıldığında bağımlılık ekleme yoluyla parametreleri bağlar. Özniteliğin bir parametreye açıkça uygulanması [FromServices]
gerekmez. Aşağıdaki kodda, her iki eylem de saati döndürür:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IDateTime, SystemDateTime>();
var app = builder.Build();
app.MapGet("/", ( IDateTime dateTime) => dateTime.Now);
app.MapGet("/fs", ([FromServices] IDateTime dateTime) => dateTime.Now);
app.Run();
İsteğe bağlı parametreler
Yol işleyicilerinde bildirilen parametreler gerekli olarak değerlendirilir:
- Bir istek yolla eşleşiyorsa, yol işleyicisi yalnızca istekte tüm gerekli parametreler sağlandığında çalışır.
- Tüm gerekli parametrelerin sağlanamaması hatayla sonuçlanır.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int pageNumber) => $"Requesting page {pageNumber}");
app.Run();
URI | result |
---|---|
/products?pageNumber=3 |
3 döndürüldü |
/products |
BadHttpRequestException : Sorgu dizesinden gerekli "int pageNumber" parametresi sağlanmadı. |
/products/1 |
HTTP 404 hatası, eşleşen yol yok |
İsteğe bağlı yapmak pageNumber
için türü isteğe bağlı olarak tanımlayın veya varsayılan bir değer sağlayın:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int? pageNumber) => $"Requesting page {pageNumber ?? 1}");
string ListProducts(int pageNumber = 1) => $"Requesting page {pageNumber}";
app.MapGet("/products2", ListProducts);
app.Run();
URI | result |
---|---|
/products?pageNumber=3 |
3 döndürüldü |
/products |
1 döndürüldü |
/products2 |
1 döndürüldü |
Yukarıdaki null atanabilir ve varsayılan değer tüm kaynaklar için geçerlidir:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/products", (Product? product) => { });
app.Run();
Yukarıdaki kod, istek gövdesi gönderilmezse null bir ürünle yöntemini çağırır.
NOT: Geçersiz veri sağlanırsa ve parametre null atanabilirse, yol işleyicisi çalıştırılmaz .
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int? pageNumber) => $"Requesting page {pageNumber ?? 1}");
app.Run();
URI | result |
---|---|
/products?pageNumber=3 |
3 Döndürülen |
/products |
1 Döndürülen |
/products?pageNumber=two |
BadHttpRequestException : "two" parametresi "Nullable<int> pageNumber" bağlanamadı. |
/products/two |
HTTP 404 hatası, eşleşen yol yok |
Daha fazla bilgi için Bağlama Hataları bölümüne bakın.
Özel türler
Aşağıdaki türler açık öznitelikler olmadan bağlanır:
HttpContext: Geçerli HTTP isteği veya yanıtı hakkındaki tüm bilgileri barındıran bağlam:
app.MapGet("/", (HttpContext context) => context.Response.WriteAsync("Hello World"));
HttpRequest ve HttpResponse: HTTP isteği ve HTTP yanıtı:
app.MapGet("/", (HttpRequest request, HttpResponse response) => response.WriteAsync($"Hello World {request.Query["name"]}"));
CancellationToken: Geçerli HTTP isteğiyle ilişkili iptal belirteci:
app.MapGet("/", async (CancellationToken cancellationToken) => await MakeLongRunningRequestAsync(cancellationToken));
ClaimsPrincipal: İstekle ilişkili kullanıcı, ile HttpContext.Userilişkili:
app.MapGet("/", (ClaimsPrincipal user) => user.Identity.Name);
İstek gövdesini veya Stream
olarak bağlama PipeReader
İstek gövdesi, kullanıcının verileri işlemesi gereken senaryoları verimli bir Stream
şekilde desteklemek için veya PipeReader
olarak bağlanabilir ve:
- Verileri blob depolamaya depolayın veya bir kuyruk sağlayıcısına sıralayın.
- Depolanan verileri bir çalışan işlemi veya bulut işleviyle işleme.
Örneğin, veriler Azure Kuyruk depolama alanına sıralanabilir veya Azure Blob depolamada depolanabilir.
Aşağıdaki kod bir arka plan kuyruğu uygular:
using System.Text.Json;
using System.Threading.Channels;
namespace BackgroundQueueService;
class BackgroundQueue : BackgroundService
{
private readonly Channel<ReadOnlyMemory<byte>> _queue;
private readonly ILogger<BackgroundQueue> _logger;
public BackgroundQueue(Channel<ReadOnlyMemory<byte>> queue,
ILogger<BackgroundQueue> logger)
{
_queue = queue;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await foreach (var dataStream in _queue.Reader.ReadAllAsync(stoppingToken))
{
try
{
var person = JsonSerializer.Deserialize<Person>(dataStream.Span)!;
_logger.LogInformation($"{person.Name} is {person.Age} " +
$"years and from {person.Country}");
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
}
}
class Person
{
public string Name { get; set; } = String.Empty;
public int Age { get; set; }
public string Country { get; set; } = String.Empty;
}
Aşağıdaki kod istek gövdesini bir Stream
ile bağlar:
app.MapPost("/register", async (HttpRequest req, Stream body,
Channel<ReadOnlyMemory<byte>> queue) =>
{
if (req.ContentLength is not null && req.ContentLength > maxMessageSize)
{
return Results.BadRequest();
}
// We're not above the message size and we have a content length, or
// we're a chunked request and we're going to read up to the maxMessageSize + 1.
// We add one to the message size so that we can detect when a chunked request body
// is bigger than our configured max.
var readSize = (int?)req.ContentLength ?? (maxMessageSize + 1);
var buffer = new byte[readSize];
// Read at least that many bytes from the body.
var read = await body.ReadAtLeastAsync(buffer, readSize, throwOnEndOfStream: false);
// We read more than the max, so this is a bad request.
if (read > maxMessageSize)
{
return Results.BadRequest();
}
// Attempt to send the buffer to the background queue.
if (queue.Writer.TryWrite(buffer.AsMemory(0..read)))
{
return Results.Accepted();
}
// We couldn't accept the message since we're overloaded.
return Results.StatusCode(StatusCodes.Status429TooManyRequests);
});
Aşağıdaki kod dosyanın tamamını Program.cs
gösterir:
using System.Threading.Channels;
using BackgroundQueueService;
var builder = WebApplication.CreateBuilder(args);
// The max memory to use for the upload endpoint on this instance.
var maxMemory = 500 * 1024 * 1024;
// The max size of a single message, staying below the default LOH size of 85K.
var maxMessageSize = 80 * 1024;
// The max size of the queue based on those restrictions
var maxQueueSize = maxMemory / maxMessageSize;
// Create a channel to send data to the background queue.
builder.Services.AddSingleton<Channel<ReadOnlyMemory<byte>>>((_) =>
Channel.CreateBounded<ReadOnlyMemory<byte>>(maxQueueSize));
// Create a background queue service.
builder.Services.AddHostedService<BackgroundQueue>();
var app = builder.Build();
// curl --request POST 'https://localhost:<port>/register' --header 'Content-Type: application/json' --data-raw '{ "Name":"Samson", "Age": 23, "Country":"Nigeria" }'
// curl --request POST "https://localhost:<port>/register" --header "Content-Type: application/json" --data-raw "{ \"Name\":\"Samson\", \"Age\": 23, \"Country\":\"Nigeria\" }"
app.MapPost("/register", async (HttpRequest req, Stream body,
Channel<ReadOnlyMemory<byte>> queue) =>
{
if (req.ContentLength is not null && req.ContentLength > maxMessageSize)
{
return Results.BadRequest();
}
// We're not above the message size and we have a content length, or
// we're a chunked request and we're going to read up to the maxMessageSize + 1.
// We add one to the message size so that we can detect when a chunked request body
// is bigger than our configured max.
var readSize = (int?)req.ContentLength ?? (maxMessageSize + 1);
var buffer = new byte[readSize];
// Read at least that many bytes from the body.
var read = await body.ReadAtLeastAsync(buffer, readSize, throwOnEndOfStream: false);
// We read more than the max, so this is a bad request.
if (read > maxMessageSize)
{
return Results.BadRequest();
}
// Attempt to send the buffer to the background queue.
if (queue.Writer.TryWrite(buffer.AsMemory(0..read)))
{
return Results.Accepted();
}
// We couldn't accept the message since we're overloaded.
return Results.StatusCode(StatusCodes.Status429TooManyRequests);
});
app.Run();
- Verileri okurken,
Stream
ile aynı nesnedirHttpRequest.Body
. - İstek gövdesi varsayılan olarak arabelleğe alınmıyor. Ceset okunduktan sonra geri alınamaz. Akış birden çok kez okunamaz.
Stream
PipeReader
ve, temel alınan arabellekler atılacağı veya yeniden kullanılacağı için en düşük eylem işleyicisi dışında kullanılamaz.
IFormFile ve IFormFileCollection kullanılarak dosya yüklemeleri
Aşağıdaki kod dosyayı karşıya yüklemek için ve IFormFileCollection kullanırIFormFile:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapPost("/upload", async (IFormFile file) =>
{
var tempFile = Path.GetTempFileName();
app.Logger.LogInformation(tempFile);
using var stream = File.OpenWrite(tempFile);
await file.CopyToAsync(stream);
});
app.MapPost("/upload_many", async (IFormFileCollection myFiles) =>
{
foreach (var file in myFiles)
{
var tempFile = Path.GetTempFileName();
app.Logger.LogInformation(tempFile);
using var stream = File.OpenWrite(tempFile);
await file.CopyToAsync(stream);
}
});
app.Run();
Kimliği doğrulanmış dosya yükleme istekleri Yetkilendirme üst bilgisi, istemci sertifikası veya cookie üst bilgi kullanılarak desteklenir.
IFormCollection, IFormFile ve IFormFileCollection ile formlara bağlama
, IFormFileve IFormFileCollection kullanarak IFormCollectionform tabanlı parametrelerden bağlama desteklenir. Swagger kullanıcı arabirimiyle tümleştirmeyi desteklemek üzere form parametreleri için OpenAPI meta verileri çıkarılır.
Aşağıdaki kod, türdeki IFormFile
çıkarımlı bağlamayı kullanarak dosyaları karşıya yükler:
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http.HttpResults;
var builder = WebApplication.CreateBuilder();
builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseAntiforgery();
string GetOrCreateFilePath(string fileName, string filesDirectory = "uploadFiles")
{
var directoryPath = Path.Combine(app.Environment.ContentRootPath, filesDirectory);
Directory.CreateDirectory(directoryPath);
return Path.Combine(directoryPath, fileName);
}
async Task UploadFileWithName(IFormFile file, string fileSaveName)
{
var filePath = GetOrCreateFilePath(fileSaveName);
await using var fileStream = new FileStream(filePath, FileMode.Create);
await file.CopyToAsync(fileStream);
}
app.MapGet("/", (HttpContext context, IAntiforgery antiforgery) =>
{
var token = antiforgery.GetAndStoreTokens(context);
var html = $"""
<html>
<body>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input name="{token.FormFieldName}" type="hidden" value="{token.RequestToken}"/>
<input type="file" name="file" placeholder="Upload an image..." accept=".jpg,
.jpeg, .png" />
<input type="submit" />
</form>
</body>
</html>
""";
return Results.Content(html, "text/html");
});
app.MapPost("/upload", async Task<Results<Ok<string>,
BadRequest<string>>> (IFormFile file, HttpContext context, IAntiforgery antiforgery) =>
{
var fileSaveName = Guid.NewGuid().ToString("N") + Path.GetExtension(file.FileName);
await UploadFileWithName(file, fileSaveName);
return TypedResults.Ok("File uploaded successfully!");
});
app.Run();
Uyarı: Formlar uygulanırken uygulamanın Siteler Arası İstek Sahteciliği (XSRF/CSRF) saldırılarını engellemesi gerekir. Yukarıdaki kodda IAntiforgery hizmet, bir sahte belirteç oluşturup doğrulayarak XSRF saldırılarını önlemek için kullanılır:
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http.HttpResults;
var builder = WebApplication.CreateBuilder();
builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseAntiforgery();
string GetOrCreateFilePath(string fileName, string filesDirectory = "uploadFiles")
{
var directoryPath = Path.Combine(app.Environment.ContentRootPath, filesDirectory);
Directory.CreateDirectory(directoryPath);
return Path.Combine(directoryPath, fileName);
}
async Task UploadFileWithName(IFormFile file, string fileSaveName)
{
var filePath = GetOrCreateFilePath(fileSaveName);
await using var fileStream = new FileStream(filePath, FileMode.Create);
await file.CopyToAsync(fileStream);
}
app.MapGet("/", (HttpContext context, IAntiforgery antiforgery) =>
{
var token = antiforgery.GetAndStoreTokens(context);
var html = $"""
<html>
<body>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input name="{token.FormFieldName}" type="hidden" value="{token.RequestToken}"/>
<input type="file" name="file" placeholder="Upload an image..." accept=".jpg,
.jpeg, .png" />
<input type="submit" />
</form>
</body>
</html>
""";
return Results.Content(html, "text/html");
});
app.MapPost("/upload", async Task<Results<Ok<string>,
BadRequest<string>>> (IFormFile file, HttpContext context, IAntiforgery antiforgery) =>
{
var fileSaveName = Guid.NewGuid().ToString("N") + Path.GetExtension(file.FileName);
await UploadFileWithName(file, fileSaveName);
return TypedResults.Ok("File uploaded successfully!");
});
app.Run();
XSRF saldırıları hakkında daha fazla bilgi için bkz . Minimal API'lerle antiforgery
Daha fazla bilgi için bkz. Minimum API'lerde form bağlama;
Formlardan koleksiyonlara ve karmaşık türlere bağlama
Bağlama aşağıdakiler için desteklenir:
Aşağıdaki kod şunları gösterir:
- Çok parçalı form girişini karmaşık bir nesneye bağlayan en düşük uç nokta.
- Antiforgery belirteçlerinin oluşturulmasını ve doğrulanması için antiforgery hizmetlerini kullanma.
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseAntiforgery();
app.MapGet("/", (HttpContext context, IAntiforgery antiforgery) =>
{
var token = antiforgery.GetAndStoreTokens(context);
var html = $"""
<html><body>
<form action="/todo" method="POST" enctype="multipart/form-data">
<input name="{token.FormFieldName}"
type="hidden" value="{token.RequestToken}" />
<input type="text" name="name" />
<input type="date" name="dueDate" />
<input type="checkbox" name="isCompleted" value="true" />
<input type="submit" />
<input name="isCompleted" type="hidden" value="false" />
</form>
</body></html>
""";
return Results.Content(html, "text/html");
});
app.MapPost("/todo", async Task<Results<Ok<Todo>, BadRequest<string>>>
([FromForm] Todo todo, HttpContext context, IAntiforgery antiforgery) =>
{
try
{
await antiforgery.ValidateRequestAsync(context);
return TypedResults.Ok(todo);
}
catch (AntiforgeryValidationException e)
{
return TypedResults.BadRequest("Invalid antiforgery token");
}
});
app.Run();
class Todo
{
public string Name { get; set; } = string.Empty;
public bool IsCompleted { get; set; } = false;
public DateTime DueDate { get; set; } = DateTime.Now.Add(TimeSpan.FromDays(1));
}
Önceki kodda:
- JSON gövdesinden okunması gereken parametrelerden ayırt etmek için hedef parametreye özniteliğiyle
[FromForm]
açıklama eklenmelidir. - İstek Temsilcisi Oluşturucu ile derlenen en düşük API'ler için karmaşık veya koleksiyon türlerinden bağlama desteklenmez .
- İşaretlemeyi adı ve değeri
false
ile ek birisCompleted
gizli giriş gösterir.isCompleted
Form gönderildiğinde onay kutusu işaretlenirse, hem değerlertrue
false
hem de değer olarak gönderilir. Onay kutusunun işareti kaldırılırsa, yalnızca gizli giriş değerifalse
gönderilir. ASP.NET Core model bağlama işlemi, birbool
değere bağlanırken yalnızca ilk değeri okur ve bu da işaretli onay kutularına vefalse
işaretsiz onay kutularına nedentrue
olur.
Önceki uç noktaya gönderilen form verilerine bir örnek aşağıdaki gibi görünür:
__RequestVerificationToken: CfDJ8Bveip67DklJm5vI2PF2VOUZ594RC8kcGWpTnVV17zCLZi1yrs-CSz426ZRRrQnEJ0gybB0AD7hTU-0EGJXDU-OaJaktgAtWLIaaEWMOWCkoxYYm-9U9eLV7INSUrQ6yBHqdMEE_aJpD4AI72gYiCqc
name: Walk the dog
dueDate: 2024-04-06
isCompleted: true
isCompleted: false
Üst bilgilerden ve sorgu dizelerinden dizileri ve dize değerlerini bağlama
Aşağıdaki kod, sorgu dizelerini ilkel türler, dize dizileri ve StringValues dizilerine bağlamayı gösterir:
// Bind query string values to a primitive type array.
// GET /tags?q=1&q=2&q=3
app.MapGet("/tags", (int[] q) =>
$"tag1: {q[0]} , tag2: {q[1]}, tag3: {q[2]}");
// Bind to a string array.
// GET /tags2?names=john&names=jack&names=jane
app.MapGet("/tags2", (string[] names) =>
$"tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}");
// Bind to StringValues.
// GET /tags3?names=john&names=jack&names=jane
app.MapGet("/tags3", (StringValues names) =>
$"tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}");
Sorgu dizelerini veya üst bilgi değerlerini karmaşık türlerden oluşan bir diziye bağlama, tür TryParse
uygulandığında desteklenir. Aşağıdaki kod bir dize dizisine bağlanır ve belirtilen etiketlere sahip tüm öğeleri döndürür:
// GET /todoitems/tags?tags=home&tags=work
app.MapGet("/todoitems/tags", async (Tag[] tags, TodoDb db) =>
{
return await db.Todos
.Where(t => tags.Select(i => i.Name).Contains(t.Tag.Name))
.ToListAsync();
});
Aşağıdaki kod modeli ve gerekli TryParse
uygulamayı gösterir:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
// This is an owned entity.
public Tag Tag { get; set; } = new();
}
[Owned]
public class Tag
{
public string? Name { get; set; } = "n/a";
public static bool TryParse(string? name, out Tag tag)
{
if (name is null)
{
tag = default!;
return false;
}
tag = new Tag { Name = name };
return true;
}
}
Aşağıdaki kod bir int
diziye bağlanır:
// GET /todoitems/query-string-ids?ids=1&ids=3
app.MapGet("/todoitems/query-string-ids", async (int[] ids, TodoDb db) =>
{
return await db.Todos
.Where(t => ids.Contains(t.Id))
.ToListAsync();
});
Yukarıdaki kodu test etmek için aşağıdaki uç noktayı ekleyerek veritabanını öğelerle Todo
doldurun:
// POST /todoitems/batch
app.MapPost("/todoitems/batch", async (Todo[] todos, TodoDb db) =>
{
await db.Todos.AddRangeAsync(todos);
await db.SaveChangesAsync();
return Results.Ok(todos);
});
Aşağıdaki verileri önceki uç noktaya geçirmek için gibi HttpRepl
bir araç kullanın:
[
{
"id": 1,
"name": "Have Breakfast",
"isComplete": true,
"tag": {
"name": "home"
}
},
{
"id": 2,
"name": "Have Lunch",
"isComplete": true,
"tag": {
"name": "work"
}
},
{
"id": 3,
"name": "Have Supper",
"isComplete": true,
"tag": {
"name": "home"
}
},
{
"id": 4,
"name": "Have Snacks",
"isComplete": true,
"tag": {
"name": "N/A"
}
}
]
Aşağıdaki kod üst bilgi anahtarına X-Todo-Id
bağlanır ve eşleşen Id
değerlere Todo
sahip öğeleri döndürür:
// GET /todoitems/header-ids
// The keys of the headers should all be X-Todo-Id with different values
app.MapGet("/todoitems/header-ids", async ([FromHeader(Name = "X-Todo-Id")] int[] ids, TodoDb db) =>
{
return await db.Todos
.Where(t => ids.Contains(t.Id))
.ToListAsync();
});
Not
Sorgu dizesinden bir string[]
bağlama yapılırken eşleşen sorgu dizesi değerinin olmaması, null değer yerine boş bir diziyle sonuçlanır.
[AsParameters] ile bağımsız değişken listeleri için parametre bağlama
AsParametersAttribute karmaşık veya özyinelemeli model bağlamasına değil, türlere basit parametre bağlamasını etkinleştirir.
Aşağıdaki kodu inceleyin:
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
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());
// Remaining code removed for brevity.
Aşağıdaki GET
uç noktayı göz önünde bulundurun:
app.MapGet("/todoitems/{id}",
async (int Id, TodoDb Db) =>
await Db.Todos.FindAsync(Id)
is Todo todo
? Results.Ok(new TodoItemDTO(todo))
: Results.NotFound());
struct
Aşağıdakiler, önceki vurgulanan parametreleri değiştirmek için kullanılabilir:
struct TodoItemRequest
{
public int Id { get; set; }
public TodoDb Db { get; set; }
}
Yeniden düzenlenmiş GET
uç nokta, AsParameters özniteliğiyle öncekini struct
kullanır:
app.MapGet("/ap/todoitems/{id}",
async ([AsParameters] TodoItemRequest request) =>
await request.Db.Todos.FindAsync(request.Id)
is Todo todo
? Results.Ok(new TodoItemDTO(todo))
: Results.NotFound());
Aşağıdaki kod, uygulamadaki ek uç noktaları gösterir:
app.MapPost("/todoitems", async (TodoItemDTO Dto, TodoDb Db) =>
{
var todoItem = new Todo
{
IsComplete = Dto.IsComplete,
Name = Dto.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 Dto, TodoDb Db) =>
{
var todo = await Db.Todos.FindAsync(Id);
if (todo is null) return Results.NotFound();
todo.Name = Dto.Name;
todo.IsComplete = Dto.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.Ok(new TodoItemDTO(todo));
}
return Results.NotFound();
});
Parametre listelerini yeniden düzenlemede aşağıdaki sınıflar kullanılır:
class CreateTodoItemRequest
{
public TodoItemDTO Dto { get; set; } = default!;
public TodoDb Db { get; set; } = default!;
}
class EditTodoItemRequest
{
public int Id { get; set; }
public TodoItemDTO Dto { get; set; } = default!;
public TodoDb Db { get; set; } = default!;
}
Aşağıdaki kod, ve önceki struct
ve sınıflarını kullanarak AsParameters
yeniden düzenlenmiş uç noktaları gösterir:
app.MapPost("/ap/todoitems", async ([AsParameters] CreateTodoItemRequest request) =>
{
var todoItem = new Todo
{
IsComplete = request.Dto.IsComplete,
Name = request.Dto.Name
};
request.Db.Todos.Add(todoItem);
await request.Db.SaveChangesAsync();
return Results.Created($"/todoitems/{todoItem.Id}", new TodoItemDTO(todoItem));
});
app.MapPut("/ap/todoitems/{id}", async ([AsParameters] EditTodoItemRequest request) =>
{
var todo = await request.Db.Todos.FindAsync(request.Id);
if (todo is null) return Results.NotFound();
todo.Name = request.Dto.Name;
todo.IsComplete = request.Dto.IsComplete;
await request.Db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/ap/todoitems/{id}", async ([AsParameters] TodoItemRequest request) =>
{
if (await request.Db.Todos.FindAsync(request.Id) is Todo todo)
{
request.Db.Todos.Remove(todo);
await request.Db.SaveChangesAsync();
return Results.Ok(new TodoItemDTO(todo));
}
return Results.NotFound();
});
Yukarıdaki parametreleri değiştirmek için aşağıdaki record
türler kullanılabilir:
record TodoItemRequest(int Id, TodoDb Db);
record CreateTodoItemRequest(TodoItemDTO Dto, TodoDb Db);
record EditTodoItemRequest(int Id, TodoItemDTO Dto, TodoDb Db);
struct
ile AsParameters
kullanmak, tür kullanmaktan record
daha yüksek performansa sahip olabilir.
AspNetCore.Docs.Samples deposundaki tam örnek kod.
Özel Bağlama
Parametre bağlamasını özelleştirmenin iki yolu vardır:
- Yol, sorgu ve üst bilgi bağlama kaynakları için, türü için statik
TryParse
bir yöntem ekleyerek özel türleri bağlayın. - Bir türe bir
BindAsync
yöntem uygulayarak bağlama işlemini denetleyin.
TryParse
TryParse
iki API'ye sahiptir:
public static bool TryParse(string value, out T result);
public static bool TryParse(string value, IFormatProvider provider, out T result);
Aşağıdaki kod URI /map?Point=12.3,10.1
ile birlikte görüntülenirPoint: 12.3, 10.1
:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// GET /map?Point=12.3,10.1
app.MapGet("/map", (Point point) => $"Point: {point.X}, {point.Y}");
app.Run();
public class Point
{
public double X { get; set; }
public double Y { get; set; }
public static bool TryParse(string? value, IFormatProvider? provider,
out Point? point)
{
// Format is "(12.3,10.1)"
var trimmedValue = value?.TrimStart('(').TrimEnd(')');
var segments = trimmedValue?.Split(',',
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (segments?.Length == 2
&& double.TryParse(segments[0], out var x)
&& double.TryParse(segments[1], out var y))
{
point = new Point { X = x, Y = y };
return true;
}
point = null;
return false;
}
}
BindAsync
BindAsync
aşağıdaki API'lere sahiptir:
public static ValueTask<T?> BindAsync(HttpContext context, ParameterInfo parameter);
public static ValueTask<T?> BindAsync(HttpContext context);
Aşağıdaki kod URI /products?SortBy=xyz&SortDir=Desc&Page=99
ile birlikte görüntülenirSortBy:xyz, SortDirection:Desc, CurrentPage:99
:
using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// GET /products?SortBy=xyz&SortDir=Desc&Page=99
app.MapGet("/products", (PagingData pageData) => $"SortBy:{pageData.SortBy}, " +
$"SortDirection:{pageData.SortDirection}, CurrentPage:{pageData.CurrentPage}");
app.Run();
public class PagingData
{
public string? SortBy { get; init; }
public SortDirection SortDirection { get; init; }
public int CurrentPage { get; init; } = 1;
public static ValueTask<PagingData?> BindAsync(HttpContext context,
ParameterInfo parameter)
{
const string sortByKey = "sortBy";
const string sortDirectionKey = "sortDir";
const string currentPageKey = "page";
Enum.TryParse<SortDirection>(context.Request.Query[sortDirectionKey],
ignoreCase: true, out var sortDirection);
int.TryParse(context.Request.Query[currentPageKey], out var page);
page = page == 0 ? 1 : page;
var result = new PagingData
{
SortBy = context.Request.Query[sortByKey],
SortDirection = sortDirection,
CurrentPage = page
};
return ValueTask.FromResult<PagingData?>(result);
}
}
public enum SortDirection
{
Default,
Asc,
Desc
}
Bağlama hataları
Bağlama başarısız olduğunda, çerçeve hata ayıklama iletisini günlüğe kaydeder ve hata moduna bağlı olarak istemciye çeşitli durum kodları döndürür.
Hata modu | Null Atanabilir Parametre Türü | Bağlama Kaynağı | Durum kodu |
---|---|---|---|
{ParameterType}.TryParse Döndürür false |
evet | route/query/header | 400 |
{ParameterType}.BindAsync Döndürür null |
evet | özel | 400 |
{ParameterType}.BindAsync Atar |
fark etmez | özel | 500 |
JSON gövdesinin seri durumdan çıkarılamaması | fark etmez | gövde | 400 |
Yanlış içerik türü (değil application/json ) |
fark etmez | gövde | Kategori 415 |
Bağlama Önceliği
Bir parametreden bağlama kaynağını belirleme kuralları:
- Parametrede (From* öznitelikleri) aşağıdaki sırayla tanımlanan açık öznitelik:
- Yol değerleri:
[FromRoute]
- Sorgu dizesi:
[FromQuery]
- Üstbilgi:
[FromHeader]
- Beden:
[FromBody]
- Form:
[FromForm]
- Hizmet:
[FromServices]
- Parametre değerleri:
[AsParameters]
- Yol değerleri:
- Özel türler
HttpContext
HttpRequest
(HttpContext.Request
)HttpResponse
(HttpContext.Response
)ClaimsPrincipal
(HttpContext.User
)CancellationToken
(HttpContext.RequestAborted
)IFormCollection
(HttpContext.Request.Form
)IFormFileCollection
(HttpContext.Request.Form.Files
)IFormFile
(HttpContext.Request.Form.Files[paramName]
)Stream
(HttpContext.Request.Body
)PipeReader
(HttpContext.Request.BodyReader
)
- Parametre türü geçerli bir statik
BindAsync
yönteme sahiptir. - Parametre türü bir dizedir veya geçerli bir statik
TryParse
yöntemi vardır.- Parametre adı örneğin, yol şablonunda varsa,
app.Map("/todo/{id}", (int id) => {});
rotadan bağlanır. - Sorgu dizesinden bağlanır.
- Parametre adı örneğin, yol şablonunda varsa,
- Parametre türü bağımlılık ekleme tarafından sağlanan bir hizmetse, kaynak olarak bu hizmeti kullanır.
- parametresi gövdedendir.
Gövde bağlaması için JSON seri durumdan çıkarma seçeneklerini yapılandırma
Gövde bağlama kaynağı seri durumdan çıkarma için kullanır System.Text.Json . Bu varsayılanı değiştirmek mümkün değildir, ancak JSON serileştirme ve seri durumdan çıkarma seçenekleri yapılandırılabilir.
JSON seri durumdan çıkarma seçeneklerini genel olarak yapılandırma
Bir uygulama için genel olarak geçerli olan seçenekler çağrılarak ConfigureHttpJsonOptionsyapılandırılabilir. Aşağıdaki örnek, ortak alanları ve JSON çıkışını biçimlendirmektedir.
var builder = WebApplication.CreateBuilder(args);
builder.Services.ConfigureHttpJsonOptions(options => {
options.SerializerOptions.WriteIndented = true;
options.SerializerOptions.IncludeFields = true;
});
var app = builder.Build();
app.MapPost("/", (Todo todo) => {
if (todo is not null) {
todo.Name = todo.NameField;
}
return todo;
});
app.Run();
class Todo {
public string? Name { get; set; }
public string? NameField;
public bool IsComplete { get; set; }
}
// If the request body contains the following JSON:
//
// {"nameField":"Walk dog", "isComplete":false}
//
// The endpoint returns the following JSON:
//
// {
// "name":"Walk dog",
// "nameField":"Walk dog",
// "isComplete":false
// }
Örnek kod hem serileştirmeyi hem de seri durumdan çıkarmayı yapılandırdığından çıktı JSON'unu okuyabilir NameField
ve içerebilir NameField
.
Uç nokta için JSON seri durumdan çıkarma seçeneklerini yapılandırma
ReadFromJsonAsync bir nesneyi kabul JsonSerializerOptions eden aşırı yüklemelere sahiptir. Aşağıdaki örnek, ortak alanları ve JSON çıkışını biçimlendirmektedir.
using System.Text.Json;
var app = WebApplication.Create();
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web) {
IncludeFields = true,
WriteIndented = true
};
app.MapPost("/", async (HttpContext context) => {
if (context.Request.HasJsonContentType()) {
var todo = await context.Request.ReadFromJsonAsync<Todo>(options);
if (todo is not null) {
todo.Name = todo.NameField;
}
return Results.Ok(todo);
}
else {
return Results.BadRequest();
}
});
app.Run();
class Todo
{
public string? Name { get; set; }
public string? NameField;
public bool IsComplete { get; set; }
}
// If the request body contains the following JSON:
//
// {"nameField":"Walk dog", "isComplete":false}
//
// The endpoint returns the following JSON:
//
// {
// "name":"Walk dog",
// "isComplete":false
// }
Yukarıdaki kod özelleştirilmiş seçenekleri yalnızca seri durumdan çıkarma işlemine uyguladığından çıktı JSON dışlar NameField
.
İstek gövdesini okuma
bir veya HttpRequest parametresini kullanarak HttpContext istek gövdesini doğrudan okuyun:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/uploadstream", async (IConfiguration config, HttpRequest request) =>
{
var filePath = Path.Combine(config["StoredFilesPath"], Path.GetRandomFileName());
await using var writeStream = File.Create(filePath);
await request.BodyReader.CopyToAsync(writeStream);
});
app.Run();
Yukarıdaki kod:
- kullanarak HttpRequest.BodyReaderistek gövdesine erişir.
- İstek gövdesini yerel bir dosyaya kopyalar.
Yanıtlar
Yol işleyicileri aşağıdaki dönüş değer türlerini destekler:
IResult
based - Buna ve dahildirTask<IResult>
ValueTask<IResult>
string
- Buna ve dahildirTask<string>
ValueTask<string>
T
(Başka herhangi bir tür) - Buna ve dahildirTask<T>
ValueTask<T>
İşleyici dönüş değerlerini yönlendirmeye yönelik daha ayrıntılı bir kılavuz için bkz. Minimal API uygulamalarında yanıt oluşturma
Örnek dönüş değerleri
dize dönüş değerleri
app.MapGet("/hello", () => "Hello World");
JSON dönüş değerleri
app.MapGet("/hello", () => new { Message = "Hello World" });
Dönüş TypedResults
Aşağıdaki kod bir TypedResultsdöndürür:
app.MapGet("/hello", () => TypedResults.Ok(new Message() { Text = "Hello World!" }));
dönüş TypedResults
, döndürmek Resultsiçin tercih edilir. Daha fazla bilgi için bkz . TypedResults vs Results.
IResult dönüş değerleri
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Aşağıdaki örnek, yanıtı özelleştirmek için yerleşik sonuç türlerini kullanır:
app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound())
.Produces<Todo>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
JSON
app.MapGet("/hello", () => Results.Json(new { Message = "Hello World" }));
Özel Durum Kodu
app.MapGet("/405", () => Results.StatusCode(405));
Metin
app.MapGet("/text", () => Results.Text("This is some text"));
Akış
var proxyClient = new HttpClient();
app.MapGet("/pokemon", async () =>
{
var stream = await proxyClient.GetStreamAsync("http://contoso/pokedex.json");
// Proxy the response as JSON
return Results.Stream(stream, "application/json");
});
Daha fazla örnek için bkz . Minimal API uygulamalarında yanıt oluşturma.
Yönlendir
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
Dosya
app.MapGet("/download", () => Results.File("myfile.text"));
Yerleşik sonuçlar
ve statik sınıflarında Results TypedResults ortak sonuç yardımcıları vardır. dönüş TypedResults
, döndürmek Results
için tercih edilir. Daha fazla bilgi için bkz . TypedResults vs Results.
Sonuçları özelleştirme
Uygulamalar özel IResult bir tür uygulayarak yanıtları denetleyebilir. Aşağıdaki kod, BIR HTML sonuç türü örneğidir:
using System.Net.Mime;
using System.Text;
static class ResultsExtensions
{
public static IResult Html(this IResultExtensions resultExtensions, string html)
{
ArgumentNullException.ThrowIfNull(resultExtensions);
return new HtmlResult(html);
}
}
class HtmlResult : IResult
{
private readonly string _html;
public HtmlResult(string html)
{
_html = html;
}
public Task ExecuteAsync(HttpContext httpContext)
{
httpContext.Response.ContentType = MediaTypeNames.Text.Html;
httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(_html);
return httpContext.Response.WriteAsync(_html);
}
}
Bu özel sonuçları daha bulunabilir hale getirmek için öğesine Microsoft.AspNetCore.Http.IResultExtensions bir uzantı yöntemi eklemenizi öneririz.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/html", () => Results.Extensions.Html(@$"<!doctype html>
<html>
<head><title>miniHTML</title></head>
<body>
<h1>Hello World</h1>
<p>The time on the server is {DateTime.Now:O}</p>
</body>
</html>"));
app.Run();
Yazılan sonuçlar
Arabirim, IResult döndürülen nesneyi HTTP yanıtına seri hale getirmek için JSON örtük desteğini kullanmayan en düşük API'lerden döndürülen değerleri temsil edebilir. Statik Results sınıfı, farklı yanıt türlerini temsil eden farklı IResult
nesneler oluşturmak için kullanılır. Örneğin, yanıt durum kodunu ayarlama veya başka bir URL'ye yönlendirme.
Uygulayan IResult
türler geneldir ve test sırasında tür onaylarına izin verir. Örneğin:
[TestClass()]
public class WeatherApiTests
{
[TestMethod()]
public void MapWeatherApiTest()
{
var result = WeatherApi.GetAllWeathers();
Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
}
}
Statik TypedResults sınıfında karşılık gelen yöntemlerin dönüş türlerine bakarak, kullanılacak doğru genel IResult
türü bulabilirsiniz.
Daha fazla örnek için bkz . Minimal API uygulamalarında yanıt oluşturma.
Filtreler
Daha fazla bilgi için bkz . Minimum API uygulamalarında filtreler.
Yetkilendirme
Yollar yetkilendirme ilkeleri kullanılarak korunabilir. Bunlar özniteliği aracılığıyla [Authorize]
veya yöntemi kullanılarak RequireAuthorization bildirilebilir:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebRPauth.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization(o => o.AddPolicy("AdminsOnly",
b => b.RequireClaim("admin", "true")));
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
var app = builder.Build();
app.UseAuthorization();
app.MapGet("/auth", [Authorize] () => "This endpoint requires authorization.");
app.MapGet("/", () => "This endpoint doesn't require authorization.");
app.MapGet("/Identity/Account/Login", () => "Sign in page at this endpoint.");
app.Run();
Yukarıdaki kod ile RequireAuthorizationyazılabilir:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Aşağıdaki örnekte ilke tabanlı yetkilendirme kullanılmaktadır:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebRPauth.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization(o => o.AddPolicy("AdminsOnly",
b => b.RequireClaim("admin", "true")));
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
var app = builder.Build();
app.UseAuthorization();
app.MapGet("/admin", [Authorize("AdminsOnly")] () =>
"The /admin endpoint is for admins only.");
app.MapGet("/admin2", () => "The /admin2 endpoint is for admins only.")
.RequireAuthorization("AdminsOnly");
app.MapGet("/", () => "This endpoint doesn't require authorization.");
app.MapGet("/Identity/Account/Login", () => "Sign in page at this endpoint.");
app.Run();
Kimliği doğrulanmamış kullanıcıların bir uç noktaya erişmesine izin verme
kimliği [AllowAnonymous]
doğrulanmamış kullanıcıların uç noktalara erişmesine izin verir:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Yollar CORS ilkeleri kullanılarak CORS etkinleştirilebilir. CORS, özniteliği veya [EnableCors]
yöntemi kullanılarak RequireCors bildirilebilir. Aşağıdaki örnekler CORS'yi etkinleştirir:
const string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
var app = builder.Build();
app.UseCors();
app.MapGet("/",() => "Hello CORS!");
app.Run();
using Microsoft.AspNetCore.Cors;
const string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
var app = builder.Build();
app.UseCors();
app.MapGet("/cors", [EnableCors(MyAllowSpecificOrigins)] () =>
"This endpoint allows cross origin requests!");
app.MapGet("/cors2", () => "This endpoint allows cross origin requests!")
.RequireCors(MyAllowSpecificOrigins);
app.Run();
Daha fazla bilgi için bkz . ASP.NET Core'da Çıkış Noktaları Arası İstekleri (CORS) Etkinleştirme
ValidateScopes ve ValidateOnBuild
ValidateScopesve ValidateOnBuild Geliştirme ortamında varsayılan olarak etkinleştirilir, ancak diğer ortamlarda devre dışı bırakılır.
olduğunda ValidateOnBuild
true
, DI kapsayıcısı derleme zamanında hizmet yapılandırmasını doğrular. Hizmet yapılandırması geçersizse derleme, hizmet istendiğinde çalışma zamanı yerine uygulama başlangıcında başarısız olur.
olduğunda ValidateScopes
true
, DI kapsayıcısı kapsamlı bir hizmetin kök kapsamdan çözümlenmediğini doğrular. Kök kapsamdan kapsamı belirlenmiş bir hizmetin çözümlenmesi, hizmet isteğin kapsamından daha uzun bellekte tutulacağından bellek sızıntısına neden olabilir.
ValidateScopes
ve ValidateOnBuild
performans nedenleriyle Geliştirme dışı modlarda varsayılan olarak yanlıştır.
Aşağıdaki kod, ValidateScopes
geliştirme modunda varsayılan olarak etkindir ancak yayın modunda devre dışıdır:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<MyScopedService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
Console.WriteLine("Development environment");
}
else
{
Console.WriteLine("Release environment");
}
app.MapGet("/", context =>
{
// Intentionally getting service provider from app, not from the request
// This causes an exception from attempting to resolve a scoped service
// outside of a scope.
// Throws System.InvalidOperationException:
// 'Cannot resolve scoped service 'MyScopedService' from root provider.'
var service = app.Services.GetRequiredService<MyScopedService>();
return context.Response.WriteAsync("Service resolved");
});
app.Run();
public class MyScopedService { }
Aşağıdaki kod, ValidateOnBuild
geliştirme modunda varsayılan olarak etkindir ancak yayın modunda devre dışıdır:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<MyScopedService>();
builder.Services.AddScoped<AnotherService>();
// System.AggregateException: 'Some services are not able to be constructed (Error
// while validating the service descriptor 'ServiceType: AnotherService Lifetime:
// Scoped ImplementationType: AnotherService': Unable to resolve service for type
// 'BrokenService' while attempting to activate 'AnotherService'.)'
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
Console.WriteLine("Development environment");
}
else
{
Console.WriteLine("Release environment");
}
app.MapGet("/", context =>
{
var service = context.RequestServices.GetRequiredService<MyScopedService>();
return context.Response.WriteAsync("Service resolved correctly!");
});
app.Run();
public class MyScopedService { }
public class AnotherService
{
public AnotherService(BrokenService brokenService) { }
}
public class BrokenService { }
Aşağıdaki kod ve ValidateOnBuild
öğesini ValidateScopes
Development
devre dışı bırakır:
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsDevelopment())
{
Console.WriteLine("Development environment");
// Doesn't detect the validation problems because ValidateScopes is false.
builder.Host.UseDefaultServiceProvider(options =>
{
options.ValidateScopes = false;
options.ValidateOnBuild = false;
});
}
Ayrıca bkz.
- En az API hızlı başvurusu
- OpenAPI belgeleri oluşturma
- Minimum API uygulamalarında yanıt oluşturma
- Minimum API uygulamalarında filtreler
- Minimum API'lerdeki hataları işleme
- Minimum API'lerde kimlik doğrulaması ve yetkilendirme
- Minimum API uygulamalarını test edin
- Kısa devre yönlendirme
- Identity API uç noktaları
- Anahtarlı hizmet bağımlılığı ekleme kapsayıcısı desteği
- En düşük API uç noktalarının arka planına bir bakış
- ASP.NET Temel Minimum API'leri düzenleme
- GitHub'da akıcı doğrulama tartışması
Bu belge:
- En düşük API'ler için hızlı başvuru sağlar.
- Deneyimli geliştiricilere yöneliktir. Giriş için bkz . Öğretici: ASP.NET Core ile minimum API oluşturma
En düşük API'ler şunlardan oluşur:
WebApplication
Aşağıdaki kod bir ASP.NET Core şablonu tarafından oluşturulur:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Yukarıdaki kod, komut satırında veya Visual Studio'da Boş Web şablonu seçerek oluşturulabilir dotnet new web
.
Aşağıdaki kod, açıkça oluşturmadan bir WebApplication WebApplicationBuilder(app
) oluşturur:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create
önceden yapılandırılmış varsayılanlarla sınıfının yeni bir örneğini WebApplication başlatır.
WebApplication
aşağıdaki ara yazılımı Minimal API applications
belirli koşullara bağlı olarak otomatik olarak ekler:
UseDeveloperExceptionPage
, olduğundaHostingEnvironment
"Development"
ilk olarak eklenir.UseRouting
, kullanıcı kodu henüz çağrılmazsaUseRouting
ve örneğinapp.MapGet
yapılandırılmış uç noktalar varsa eklenir.UseEndpoints
, herhangi bir uç nokta yapılandırılırsa ara yazılım işlem hattının sonuna eklenir.UseAuthentication
kullanıcı kodu henüz çağrılmazsaUseAuthentication
ve hizmet sağlayıcısında algılanabilirseIAuthenticationSchemeProvider
hemen sonraUseRouting
eklenir.IAuthenticationSchemeProvider
kullanılırkenAddAuthentication
varsayılan olarak eklenir ve kullanılarak hizmetler algılanırIServiceProviderIsService
.UseAuthorization
, kullanıcı kodu henüz çağrılmazsaUseAuthorization
ve hizmet sağlayıcısında algılanabilirseIAuthorizationHandlerProvider
eklenir.IAuthorizationHandlerProvider
kullanılırkenAddAuthorization
varsayılan olarak eklenir ve kullanılarak hizmetler algılanırIServiceProviderIsService
.- Kullanıcı tarafından yapılandırılmış ara yazılım ve uç noktalar ile
UseEndpoints
arasınaUseRouting
eklenir.
Aşağıdaki kod, uygulamaya eklenen otomatik ara yazılımların etkili bir şekilde ürettiği koddur:
if (isDevelopment)
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
if (isAuthenticationConfigured)
{
app.UseAuthentication();
}
if (isAuthorizationConfigured)
{
app.UseAuthorization();
}
// user middleware/endpoints
app.CustomMiddleware(...);
app.MapGet("/", () => "hello world");
// end user middleware/endpoints
app.UseEndpoints(e => {});
Bazı durumlarda, varsayılan ara yazılım yapılandırması uygulama için doğru değildir ve değişiklik gerektirir. Örneğin, UseCors ve UseAuthorizationöncesinde UseAuthentication çağrılmalıdır. Uygulamanın çağrısı UseAuthentication
UseAuthorization
ve çağrılıp çağrılmaması UseCors
gerekir:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Yol eşleştirme gerçekleşmeden önce ara yazılım çalıştırılmalıdır, UseRouting çağrılmalı ve ara yazılım çağrısından UseRouting
önce yerleştirilmelidir. UseEndpoints daha önce açıklandığı gibi otomatik olarak eklendiğinden bu durumda gerekli değildir:
app.Use((context, next) =>
{
return next(context);
});
app.UseRouting();
// other middleware and endpoints
Terminal ara yazılımı eklerken:
- Ara yazılım, sonrasında
UseEndpoints
eklenmelidir. - Terminal ara yazılımının doğru konuma yerleştirilebilmesi için uygulamanın araması
UseRouting
UseEndpoints
gerekir.
app.UseRouting();
app.MapGet("/", () => "hello world");
app.UseEndpoints(e => {});
app.Run(context =>
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
Terminal ara yazılımı, isteği hiçbir uç nokta işlemezse çalışan ara yazılımdır.
Bağlantı noktalarıyla çalışma
Visual Studio veya dotnet new
ile bir web uygulaması oluşturulduğunda, uygulamanın yanıt verdiği bağlantı noktalarını belirten bir Properties/launchSettings.json
dosya oluşturulur. Sonraki bağlantı noktası ayarı örneklerinde, uygulamayı Visual Studio'dan çalıştırmak bir hata iletişim kutusu Unable to connect to web server 'AppName'
döndürür. Visual Studio, içinde Properties/launchSettings.json
belirtilen bağlantı noktasını beklediğinden ancak uygulama tarafından app.Run("http://localhost:3000")
belirtilen bağlantı noktasını kullandığından bir hata döndürür. Komut satırından örnekleri değiştirerek aşağıdaki bağlantı noktasını çalıştırın.
Aşağıdaki bölümlerde uygulamanın yanıt verdiği bağlantı noktası ayarlanır.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
Önceki kodda uygulama bağlantı noktasına 3000
yanıt verir.
Birden çok bağlantı noktası
Aşağıdaki kodda uygulama ve 4000
bağlantı noktasına 3000
yanıt verir.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
Komut satırından bağlantı noktasını ayarlama
Aşağıdaki komut, uygulamanın bağlantı noktasına 7777
yanıt vermesini sağlar:
dotnet run --urls="https://localhost:7777"
Kestrel Uç nokta dosyada appsettings.json
da yapılandırılmışsa, appsettings.json
belirtilen dosya URL'si kullanılır. Daha fazla bilgi için bkz. Kestrel uç nokta yapılandırması
Bağlantı noktasını ortamdan okuma
Aşağıdaki kod, bağlantı noktasını ortamdan okur:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
Bağlantı noktasını ortamdan ayarlamanın tercih edilen yolu, aşağıdaki bölümde gösterilen ortam değişkenini kullanmaktır ASPNETCORE_URLS
.
ASPNETCORE_URLS ortam değişkeni aracılığıyla bağlantı noktalarını ayarlama
Ortam ASPNETCORE_URLS
değişkeni, bağlantı noktasını ayarlamak için kullanılabilir:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS
birden çok URL'leri destekler:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
Ortamı kullanma hakkında daha fazla bilgi için bkz . ASP.NET Core'da birden çok ortam kullanma
Tüm arabirimlerde dinleme
Aşağıdaki örneklerde tüm arabirimlerde dinleme gösterilmektedir
http://*:3000
var app = WebApplication.Create(args);
app.Urls.Add("http://*:3000");
app.MapGet("/", () => "Hello World");
app.Run();
http://+:3000
var app = WebApplication.Create(args);
app.Urls.Add("http://+:3000");
app.MapGet("/", () => "Hello World");
app.Run();
http://0.0.0.0:3000
var app = WebApplication.Create(args);
app.Urls.Add("http://0.0.0.0:3000");
app.MapGet("/", () => "Hello World");
app.Run();
ASPNETCORE_URLS kullanarak tüm arabirimlerde dinleme
Önceki örnekler kullanabilir ASPNETCORE_URLS
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
Geliştirme sertifikası ile HTTPS belirtme
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Geliştirme sertifikası hakkında daha fazla bilgi için bkz . Windows ve macOS'ta ASP.NET Core HTTPS geliştirme sertifikasına güvenme.
Özel sertifika kullanarak HTTPS belirtme
Aşağıdaki bölümlerde, dosyayı kullanarak ve yapılandırma yoluyla özel sertifikanın nasıl belirtileceğini gösterilmektedir appsettings.json
.
Ile özel sertifikayı belirtin appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Yapılandırma aracılığıyla özel sertifikayı belirtme
var builder = WebApplication.CreateBuilder(args);
// Configure the cert and the key
builder.Configuration["Kestrel:Certificates:Default:Path"] = "cert.pem";
builder.Configuration["Kestrel:Certificates:Default:KeyPath"] = "key.pem";
var app = builder.Build();
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Sertifika API'lerini kullanma
using System.Security.Cryptography.X509Certificates;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
options.ConfigureHttpsDefaults(httpsOptions =>
{
var certPath = Path.Combine(builder.Environment.ContentRootPath, "cert.pem");
var keyPath = Path.Combine(builder.Environment.ContentRootPath, "key.pem");
httpsOptions.ServerCertificate = X509Certificate2.CreateFromPemFile(certPath,
keyPath);
});
});
var app = builder.Build();
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Yapılandırma
Aşağıdaki kod yapılandırma sisteminden okunur:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Config failed!";
app.MapGet("/", () => message);
app.Run();
Daha fazla bilgi için bkz . ASP.NET Core'da yapılandırma
Günlük Kaydı
Aşağıdaki kod, oturum açma uygulaması başlatma işlemine bir ileti yazar:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
Daha fazla bilgi için bkz . .NET Core ve ASP.NET Core'da oturum açma
Bağımlılık Ekleme (DI) kapsayıcıya erişme
Aşağıdaki kod, uygulama başlatma sırasında DI kapsayıcısından hizmet almayı gösterir:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddScoped<SampleService>();
var app = builder.Build();
app.MapControllers();
using (var scope = app.Services.CreateScope())
{
var sampleService = scope.ServiceProvider.GetRequiredService<SampleService>();
sampleService.DoSomething();
}
app.Run();
Daha fazla bilgi için, bkz. ASP.NET Core'de bağımlılık ekleme.
WebApplicationBuilder
Bu bölüm, kullanan WebApplicationBuilderörnek kodu içerir.
İçerik kökünü, uygulama adını ve ortamı değiştirme
Aşağıdaki kod içerik kökünü, uygulama adını ve ortamı ayarlar:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
ApplicationName = typeof(Program).Assembly.FullName,
ContentRootPath = Directory.GetCurrentDirectory(),
EnvironmentName = Environments.Staging,
WebRootPath = "customwwwroot"
});
Console.WriteLine($"Application Name: {builder.Environment.ApplicationName}");
Console.WriteLine($"Environment Name: {builder.Environment.EnvironmentName}");
Console.WriteLine($"ContentRoot Path: {builder.Environment.ContentRootPath}");
Console.WriteLine($"WebRootPath: {builder.Environment.WebRootPath}");
var app = builder.Build();
WebApplication.CreateBuilder önceden yapılandırılmış varsayılanlarla WebApplicationBuilder sınıfının yeni bir örneğini başlatır.
Daha fazla bilgi için bkz . ASP.NET Temel bilgilere genel bakış
İçerik kökünü, uygulama adını ve ortamı ortam değişkenlerine veya komut satırına göre değiştirme
Aşağıdaki tabloda içerik kökünü, uygulama adını ve ortamı değiştirmek için kullanılan ortam değişkeni ve komut satırı bağımsız değişkeni gösterilmektedir:
özelliği | Ortam değişkeni | Komut satırı bağımsız değişkeni |
---|---|---|
Uygulama adı | ASPNETCORE_APPLICATIONNAME | --applicationName |
Ortam adı | ASPNETCORE_ENVIRONMENT | --çevre |
İçerik kökü | ASPNETCORE_CONTENTROOT | --contentRoot |
Yapılandırma sağlayıcıları ekleme
Aşağıdaki örnek INI yapılandırma sağlayıcısını ekler:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Ayrıntılı bilgi için bkz. ASP.NET Core'da Yapılandırma bölümünde dosya yapılandırma sağlayıcıları.
Yapılandırmayı okuma
Varsayılan olarak WebApplicationBuilder , yapılandırmayı aşağıdakiler dahil olmak üzere birden çok kaynaktan okur:
appSettings.json
veappSettings.{environment}.json
- Ortam değişkenleri
- Komut satırı
Aşağıdaki kod yapılandırmadan okur HelloKey
ve değeri uç noktada görüntüler /
. Yapılandırma değeri null ise , "Hello" öğesine message
atanır:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
Okunan yapılandırma kaynaklarının tam listesi için bkz. ASP.NET Core'da Yapılandırma'da varsayılan yapılandırma
Günlük sağlayıcıları ekleme
var builder = WebApplication.CreateBuilder(args);
// Configure JSON logging to the console.
builder.Logging.AddJsonConsole();
var app = builder.Build();
app.MapGet("/", () => "Hello JSON console!");
app.Run();
Hizmet ekleme
var builder = WebApplication.CreateBuilder(args);
// Add the memory cache services.
builder.Services.AddMemoryCache();
// Add a custom scoped service.
builder.Services.AddScoped<ITodoRepository, TodoRepository>();
var app = builder.Build();
IHostBuilder'i özelleştirme
üzerindeki IHostBuilder mevcut uzantı yöntemlerine Host özelliği kullanılarak erişilebilir:
var builder = WebApplication.CreateBuilder(args);
// Wait 30 seconds for graceful shutdown.
builder.Host.ConfigureHostOptions(o => o.ShutdownTimeout = TimeSpan.FromSeconds(30));
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
IWebHostBuilder'i özelleştirme
üzerindeki IWebHostBuilder uzantı yöntemlerine WebApplicationBuilder.WebHost özelliği kullanılarak erişilebilir.
var builder = WebApplication.CreateBuilder(args);
// Change the HTTP server implemenation to be HTTP.sys based
builder.WebHost.UseHttpSys();
var app = builder.Build();
app.MapGet("/", () => "Hello HTTP.sys");
app.Run();
Web kökünü değiştirme
Varsayılan olarak, web kökü klasördeki içerik köküne wwwroot
göredir. Web kökü, statik dosyalar ara yazılımının statik dosyaları ara yazılımının ara yazılım tarafından arandığı yerdir. Web kökü ile, komut satırıyla WebHostOptions
veya yöntemiyle UseWebRoot değiştirilebilir:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Özel bağımlılık ekleme (DI) kapsayıcısı
Aşağıdaki örnekte Autofac kullanılır:
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
// Register services directly with Autofac here. Don't
// call builder.Populate(), that happens in AutofacServiceProviderFactory.
builder.Host.ConfigureContainer<ContainerBuilder>(builder => builder.RegisterModule(new MyApplicationModule()));
var app = builder.Build();
Ara Yazılım Ekle
Mevcut ASP.NET Core ara yazılımları üzerinde WebApplication
yapılandırılabilir:
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
Daha fazla bilgi için bkz . ASP.NET Core Ara Yazılımı
Geliştirici özel durum sayfası
WebApplication.CreateBuilder önceden yapılandırılmış varsayılanlarla sınıfının yeni bir örneğini WebApplicationBuilder başlatır. Geliştirici özel durum sayfası önceden yapılandırılmış varsayılanlarda etkinleştirilir. Geliştirme ortamında aşağıdaki kod çalıştırıldığında, öğesine /
gitmek özel durumu gösteren kolay bir sayfa oluşturur.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () =>
{
throw new InvalidOperationException("Oops, the '/' route has thrown an exception.");
});
app.Run();
ASP.NET Core Ara Yazılımı
Aşağıdaki tabloda en az API ile sık kullanılan ara yazılımlardan bazıları listelanmaktadır.
Ara yazılım | Açıklama | API |
---|---|---|
Kimlik Doğrulaması | Kimlik doğrulaması desteği sağlar. | UseAuthentication |
Yetkilendirme | Yetkilendirme desteği sağlar. | UseAuthorization |
CORS | Çıkış Noktaları Arası Kaynak Paylaşımı'nı yapılandırır. | UseCors |
Özel Durum İşleyicisi | Ara yazılım işlem hattı tarafından oluşan özel durumları genel olarak işler. | UseExceptionHandler |
İletilen Üst Bilgiler | Taşınan üst bilgileri geçerli isteğe iletir. | UseForwardedHeaders |
HTTPS Yeniden Yönlendirme | Tüm HTTP isteklerini HTTPS'ye yönlendirir. | UseHttpsRedirection |
HTTP Katı Aktarım Güvenliği (HSTS) | Özel bir yanıt üst bilgisi ekleyen güvenlik iyileştirme ara yazılımı. | UseHsts |
İstek Günlüğü | HTTP isteklerini ve yanıtlarını günlüğe kaydetme desteği sağlar. | UseHttpLogging |
İstek Zaman Aşımları | İstek zaman aşımlarını, genel varsayılan ve uç nokta başına yapılandırma desteği sağlar. | UseRequestTimeouts |
W3C İstek Günlüğü | HTTP isteklerini ve yanıtlarını W3C biçiminde günlüğe kaydetme desteği sağlar. | UseW3CLogging |
Yanıtları Önbelleğe Alma | Yanıtları önbelleğe almak için destek sağlar. | UseResponseCaching |
Yanıt Sıkıştırma | Yanıtları sıkıştırma desteği sağlar. | UseResponseCompression |
Oturum | Kullanıcı oturumlarını yönetmek için destek sağlar. | UseSession |
Statik Dosyalar | Statik dosyalara ve dizine göz atma desteği sağlar. | UseStaticFiles, UseFileServer |
WebSockets | WebSockets protokolünü etkinleştirir. | UseWebSockets |
Aşağıdaki bölümler istek işlemeyi kapsar: yönlendirme, parametre bağlama ve yanıtlar.
Yönlendirme
Yapılandırılmış WebApplication
bir , veya Delete
gibi Get
Post
Put
bir deve büyük/küçük harfli HTTP yöntemini destekler Map{Verb}
ve MapMethods buradadır:{Verb}
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "This is a GET");
app.MapPost("/", () => "This is a POST");
app.MapPut("/", () => "This is a PUT");
app.MapDelete("/", () => "This is a DELETE");
app.MapMethods("/options-or-head", new[] { "OPTIONS", "HEAD" },
() => "This is an options or head request ");
app.Run();
Delegate Bu yöntemlere geçirilen bağımsız değişkenler "yol işleyicileri" olarak adlandırılır.
Yol İşleyicileri
Yol işleyicileri, yol eşleştiğinde yürütülen yöntemlerdir. Yol işleyicileri bir lambda ifadesi, yerel bir işlev, örnek yöntemi veya statik bir yöntem olabilir. Yol işleyicileri zaman uyumlu veya zaman uyumsuz olabilir.
Lambda ifadesi
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/inline", () => "This is an inline lambda");
var handler = () => "This is a lambda variable";
app.MapGet("/", handler);
app.Run();
Yerel işlev
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Örnek yöntemi
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var handler = new HelloHandler();
app.MapGet("/", handler.Hello);
app.Run();
class HelloHandler
{
public string Hello()
{
return "Hello Instance method";
}
}
Statik yöntem
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", HelloHandler.Hello);
app.Run();
class HelloHandler
{
public static string Hello()
{
return "Hello static method";
}
}
Uç noktanın dışında tanımlanmış Program.cs
En az API'nin içinde Program.cs
bulunması gerekmez.
Program.cs
using MinAPISeparateFile;
var builder = WebApplication.CreateSlimBuilder(args);
var app = builder.Build();
TodoEndpoints.Map(app);
app.Run();
TodoEndpoints.cs
namespace MinAPISeparateFile;
public static class TodoEndpoints
{
public static void Map(WebApplication app)
{
app.MapGet("/", async context =>
{
// Get all todo items
await context.Response.WriteAsJsonAsync(new { Message = "All todo items" });
});
app.MapGet("/{id}", async context =>
{
// Get one todo item
await context.Response.WriteAsJsonAsync(new { Message = "One todo item" });
});
}
}
Ayrıca bu makalenin devamında Grupları yönlendirme bölümüne bakın.
Adlandırılmış uç noktalar ve bağlantı oluşturma
Uç noktaya URL'ler oluşturmak için uç noktalara adlar verilebilir. Adlandırılmış uç nokta kullanmak, bir uygulamada yolları sabit kodlamaktan kaçınıyor:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/hello", () => "Hello named route")
.WithName("hi");
app.MapGet("/", (LinkGenerator linker) =>
$"The link to the hello route is {linker.GetPathByName("hi", values: null)}");
app.Run();
Yukarıdaki kod uç noktadan görüntülenir The link to the hello route is /hello
/
.
NOT: Uç nokta adları büyük/küçük harfe duyarlıdır.
Uç nokta adları:
- Genel olarak benzersiz olması gerekir.
- OpenAPI desteği etkinleştirildiğinde OpenAPI işlem kimliği olarak kullanılır. Daha fazla bilgi için bkz . OpenAPI.
Rota Parametreleri
Yol parametreleri, yol deseni tanımının bir parçası olarak yakalanabilir:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/users/{userId}/books/{bookId}",
(int userId, int bookId) => $"The user id is {userId} and book id is {bookId}");
app.Run();
Yukarıdaki kod URI'sinden /users/3/books/7
döndürürThe user id is 3 and book id is 7
.
Yol işleyicisi, yakalanacak parametreleri bildirebilir. Yakalamak üzere bildirilen parametrelerle bir yola istek yapıldığında, parametreler ayrıştırılır ve işleyiciye geçirilir. Bu, değerleri güvenli bir şekilde tür olarak yakalamayı kolaylaştırır. Önceki kodda userId
ve bookId
her ikisi de int
şeklindedir.
Yukarıdaki kodda, herhangi bir yol değeri bir int
'a dönüştürülemezse bir özel durum oluşturulur. GET isteği /users/hello/books/3
aşağıdaki özel durumu oluşturur:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Joker karakter ve tüm yolları yakalama
Aşağıdaki catch all route returns Routing to hello
from the '/posts/hello' endpoint:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Yol kısıtlamaları
Yol kısıtlamaları, bir yolun eşleşen davranışını kısıtlar.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/todos/{id:int}", (int id) => db.Todos.Find(id));
app.MapGet("/todos/{text}", (string text) => db.Todos.Where(t => t.Text.Contains(text));
app.MapGet("/posts/{slug:regex(^[a-z0-9_-]+$)}", (string slug) => $"Post {slug}");
app.Run();
Aşağıdaki tabloda, önceki yol şablonları ve bunların davranışları gösterilmektedir:
Rota Şablonu | Örnek Eşleşen URI |
---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
Daha fazla bilgi için bkz. ASP.NET Core'da Yönlendirme bölümünde yönlendirme kısıtlaması başvurusu.
Yol grupları
Uzantı yöntemi, MapGroup ortak bir ön eke sahip uç nokta gruplarını düzenlemeye yardımcı olur. Yinelenen kodu azaltır ve uç nokta meta verilerini ekleyen ve WithMetadata gibi RequireAuthorization yöntemlere tek bir çağrıyla tüm uç nokta gruplarını özelleştirmeye olanak tanır.
Örneğin, aşağıdaki kod iki benzer uç nokta grubu oluşturur:
app.MapGroup("/public/todos")
.MapTodosApi()
.WithTags("Public");
app.MapGroup("/private/todos")
.MapTodosApi()
.WithTags("Private")
.AddEndpointFilterFactory(QueryPrivateTodos)
.RequireAuthorization();
EndpointFilterDelegate QueryPrivateTodos(EndpointFilterFactoryContext factoryContext, EndpointFilterDelegate next)
{
var dbContextIndex = -1;
foreach (var argument in factoryContext.MethodInfo.GetParameters())
{
if (argument.ParameterType == typeof(TodoDb))
{
dbContextIndex = argument.Position;
break;
}
}
// Skip filter if the method doesn't have a TodoDb parameter.
if (dbContextIndex < 0)
{
return next;
}
return async invocationContext =>
{
var dbContext = invocationContext.GetArgument<TodoDb>(dbContextIndex);
dbContext.IsPrivate = true;
try
{
return await next(invocationContext);
}
finally
{
// This should only be relevant if you're pooling or otherwise reusing the DbContext instance.
dbContext.IsPrivate = false;
}
};
}
public static RouteGroupBuilder MapTodosApi(this RouteGroupBuilder group)
{
group.MapGet("/", GetAllTodos);
group.MapGet("/{id}", GetTodo);
group.MapPost("/", CreateTodo);
group.MapPut("/{id}", UpdateTodo);
group.MapDelete("/{id}", DeleteTodo);
return group;
}
Bu senaryoda, sonuçta üst bilgi 201 Created
için Location
göreli bir adres kullanabilirsiniz:
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
İlk uç nokta grubu yalnızca ön ekli /public/todos
isteklerle eşleşir ve kimlik doğrulaması olmadan erişilebilir. İkinci uç nokta grubu yalnızca ön ekli isteklerle /private/todos
eşleşir ve kimlik doğrulaması gerektirir.
QueryPrivateTodos
Uç nokta filtresi fabrikası, özel todo verilerine erişmeye ve bunları depolamaya izin vermek için yol işleyicisinin TodoDb
parametrelerini değiştiren yerel bir işlevdir.
Yol grupları, yol parametreleri ve kısıtlamalarıyla iç içe grupları ve karmaşık ön ek desenlerini de destekler. Aşağıdaki örnekte, gruba eşlenen user
ve yol işleyicisi dış grup ön eklerinde tanımlanan ve {group}
yol parametrelerini yakalayabilir{org}
.
Ön ek de boş olabilir. Bu, yol desenini değiştirmeden bir uç nokta grubuna uç nokta meta verileri veya filtreleri eklemek için yararlı olabilir.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
Bir gruba filtre veya meta veri eklemek, bir iç gruba veya belirli bir uç noktaya eklenmiş olabilecek ek filtreler veya meta veriler eklemeden önce bunları her uç noktaya tek tek eklemekle aynı şekilde davranır.
var outer = app.MapGroup("/outer");
var inner = outer.MapGroup("/inner");
inner.AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("/inner group filter");
return next(context);
});
outer.AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("/outer group filter");
return next(context);
});
inner.MapGet("/", () => "Hi!").AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("MapGet filter");
return next(context);
});
Yukarıdaki örnekte dış filtre, ikinci kez eklenmiş olsa bile gelen isteği iç filtreden önce günlüğe kaydeder. Filtreler farklı gruplara uygulandığından, birbirlerine göre eklendikleri sıra önemli değildir. Sipariş filtrelerinin eklenmesi, aynı gruba veya belirli bir uç noktaya uygulandığında önemlidir.
için bir istek /outer/inner/
aşağıdakileri günlüğe kaydeder:
/outer group filter
/inner group filter
MapGet filter
Parametre bağlama
Parametre bağlama, istek verilerini yol işleyicileri tarafından ifade edilen kesin olarak belirlenmiş parametrelere dönüştürme işlemidir. Bağlama kaynağı, parametrelerin nereye bağlandığını belirler. Bağlama kaynakları HTTP yöntemine ve parametre türüne göre açık veya çıkarılabilir.
Desteklenen bağlama kaynakları:
- Yol değerleri
- Sorgu dizesi
- Üst bilgi
- Gövde (JSON olarak)
- Bağımlılık ekleme tarafından sağlanan hizmetler
- Özel
.NET 6 ve 7'de form değerlerinden bağlama yerel olarak desteklenmez.
Aşağıdaki GET
yol işleyicisi bu parametre bağlama kaynaklarından bazılarını kullanır:
var builder = WebApplication.CreateBuilder(args);
// Added as service
builder.Services.AddSingleton<Service>();
var app = builder.Build();
app.MapGet("/{id}", (int id,
int page,
[FromHeader(Name = "X-CUSTOM-HEADER")] string customHeader,
Service service) => { });
class Service { }
Aşağıdaki tabloda, önceki örnekte kullanılan parametrelerle ilişkili bağlama kaynakları arasındaki ilişki gösterilmektedir.
Parametre | Bağlama Kaynağı |
---|---|
id |
yol değeri |
page |
sorgu dizesi |
customHeader |
üst bilgi |
service |
Bağımlılık ekleme tarafından sağlanır |
, , HEAD
OPTIONS
ve DELETE
HTTP yöntemleri GET
gövdeden örtük olarak bağlanmaz. Bu HTTP yöntemleri için gövdeden (JSON olarak) bağlanmak için ile [FromBody]
açıkça bağlayın veya dosyasından HttpRequestokuyun.
Aşağıdaki örnek POST yol işleyicisi, parametresi için person
bir bağlama gövdesi kaynağı (JSON olarak) kullanır:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/", (Person person) => { });
record Person(string Name, int Age);
Yukarıdaki örneklerde yer alan parametrelerin tümü istek verilerinden otomatik olarak bağlıdır. Parametre bağlamanın sağladığı kolaylığı göstermek için aşağıdaki yol işleyicileri istek verilerini doğrudan istekten nasıl okuyacaklarını gösterir:
app.MapGet("/{id}", (HttpRequest request) =>
{
var id = request.RouteValues["id"];
var page = request.Query["page"];
var customHeader = request.Headers["X-CUSTOM-HEADER"];
// ...
});
app.MapPost("/", async (HttpRequest request) =>
{
var person = await request.ReadFromJsonAsync<Person>();
// ...
});
Açık Parametre Bağlama
Öznitelikler, parametrelerin nereye bağlı olduğunu açıkça bildirmek için kullanılabilir.
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
// Added as service
builder.Services.AddSingleton<Service>();
var app = builder.Build();
app.MapGet("/{id}", ([FromRoute] int id,
[FromQuery(Name = "p")] int page,
[FromServices] Service service,
[FromHeader(Name = "Content-Type")] string contentType)
=> {});
class Service { }
record Person(string Name, int Age);
Parametre | Bağlama Kaynağı |
---|---|
id |
adıyla yol değeri id |
page |
adlı sorgu dizesi "p" |
service |
Bağımlılık ekleme tarafından sağlanır |
contentType |
adıyla üst bilgi "Content-Type" |
Not
.NET 6 ve 7'de form değerlerinden bağlama yerel olarak desteklenmez.
Bağımlılık ekleme ile parametre bağlama
En düşük API'ler için parametre bağlama, tür hizmet olarak yapılandırıldığında bağımlılık ekleme yoluyla parametreleri bağlar. Özniteliğin bir parametreye açıkça uygulanması [FromServices]
gerekmez. Aşağıdaki kodda, her iki eylem de saati döndürür:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IDateTime, SystemDateTime>();
var app = builder.Build();
app.MapGet("/", ( IDateTime dateTime) => dateTime.Now);
app.MapGet("/fs", ([FromServices] IDateTime dateTime) => dateTime.Now);
app.Run();
İsteğe bağlı parametreler
Yol işleyicilerinde bildirilen parametreler gerekli olarak değerlendirilir:
- Bir istek yolla eşleşiyorsa, yol işleyicisi yalnızca istekte tüm gerekli parametreler sağlandığında çalışır.
- Tüm gerekli parametrelerin sağlanamaması hatayla sonuçlanır.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int pageNumber) => $"Requesting page {pageNumber}");
app.Run();
URI | result |
---|---|
/products?pageNumber=3 |
3 döndürüldü |
/products |
BadHttpRequestException : Sorgu dizesinden gerekli "int pageNumber" parametresi sağlanmadı. |
/products/1 |
HTTP 404 hatası, eşleşen yol yok |
İsteğe bağlı yapmak pageNumber
için türü isteğe bağlı olarak tanımlayın veya varsayılan bir değer sağlayın:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int? pageNumber) => $"Requesting page {pageNumber ?? 1}");
string ListProducts(int pageNumber = 1) => $"Requesting page {pageNumber}";
app.MapGet("/products2", ListProducts);
app.Run();
URI | result |
---|---|
/products?pageNumber=3 |
3 döndürüldü |
/products |
1 döndürüldü |
/products2 |
1 döndürüldü |
Yukarıdaki null atanabilir ve varsayılan değer tüm kaynaklar için geçerlidir:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/products", (Product? product) => { });
app.Run();
Yukarıdaki kod, istek gövdesi gönderilmezse null bir ürünle yöntemini çağırır.
NOT: Geçersiz veri sağlanırsa ve parametre null atanabilirse, yol işleyicisi çalıştırılmaz .
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int? pageNumber) => $"Requesting page {pageNumber ?? 1}");
app.Run();
URI | result |
---|---|
/products?pageNumber=3 |
3 Döndürülen |
/products |
1 Döndürülen |
/products?pageNumber=two |
BadHttpRequestException : "two" parametresi "Nullable<int> pageNumber" bağlanamadı. |
/products/two |
HTTP 404 hatası, eşleşen yol yok |
Daha fazla bilgi için Bağlama Hataları bölümüne bakın.
Özel türler
Aşağıdaki türler açık öznitelikler olmadan bağlanır:
HttpContext: Geçerli HTTP isteği veya yanıtı hakkındaki tüm bilgileri barındıran bağlam:
app.MapGet("/", (HttpContext context) => context.Response.WriteAsync("Hello World"));
HttpRequest ve HttpResponse: HTTP isteği ve HTTP yanıtı:
app.MapGet("/", (HttpRequest request, HttpResponse response) => response.WriteAsync($"Hello World {request.Query["name"]}"));
CancellationToken: Geçerli HTTP isteğiyle ilişkili iptal belirteci:
app.MapGet("/", async (CancellationToken cancellationToken) => await MakeLongRunningRequestAsync(cancellationToken));
ClaimsPrincipal: İstekle ilişkili kullanıcı, ile HttpContext.Userilişkili:
app.MapGet("/", (ClaimsPrincipal user) => user.Identity.Name);
İstek gövdesini veya Stream
olarak bağlama PipeReader
İstek gövdesi, kullanıcının verileri işlemesi gereken senaryoları verimli bir Stream
şekilde desteklemek için veya PipeReader
olarak bağlanabilir ve:
- Verileri blob depolamaya depolayın veya bir kuyruk sağlayıcısına sıralayın.
- Depolanan verileri bir çalışan işlemi veya bulut işleviyle işleme.
Örneğin, veriler Azure Kuyruk depolama alanına sıralanabilir veya Azure Blob depolamada depolanabilir.
Aşağıdaki kod bir arka plan kuyruğu uygular:
using System.Text.Json;
using System.Threading.Channels;
namespace BackgroundQueueService;
class BackgroundQueue : BackgroundService
{
private readonly Channel<ReadOnlyMemory<byte>> _queue;
private readonly ILogger<BackgroundQueue> _logger;
public BackgroundQueue(Channel<ReadOnlyMemory<byte>> queue,
ILogger<BackgroundQueue> logger)
{
_queue = queue;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await foreach (var dataStream in _queue.Reader.ReadAllAsync(stoppingToken))
{
try
{
var person = JsonSerializer.Deserialize<Person>(dataStream.Span)!;
_logger.LogInformation($"{person.Name} is {person.Age} " +
$"years and from {person.Country}");
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
}
}
class Person
{
public string Name { get; set; } = String.Empty;
public int Age { get; set; }
public string Country { get; set; } = String.Empty;
}
Aşağıdaki kod istek gövdesini bir Stream
ile bağlar:
app.MapPost("/register", async (HttpRequest req, Stream body,
Channel<ReadOnlyMemory<byte>> queue) =>
{
if (req.ContentLength is not null && req.ContentLength > maxMessageSize)
{
return Results.BadRequest();
}
// We're not above the message size and we have a content length, or
// we're a chunked request and we're going to read up to the maxMessageSize + 1.
// We add one to the message size so that we can detect when a chunked request body
// is bigger than our configured max.
var readSize = (int?)req.ContentLength ?? (maxMessageSize + 1);
var buffer = new byte[readSize];
// Read at least that many bytes from the body.
var read = await body.ReadAtLeastAsync(buffer, readSize, throwOnEndOfStream: false);
// We read more than the max, so this is a bad request.
if (read > maxMessageSize)
{
return Results.BadRequest();
}
// Attempt to send the buffer to the background queue.
if (queue.Writer.TryWrite(buffer.AsMemory(0..read)))
{
return Results.Accepted();
}
// We couldn't accept the message since we're overloaded.
return Results.StatusCode(StatusCodes.Status429TooManyRequests);
});
Aşağıdaki kod dosyanın tamamını Program.cs
gösterir:
using System.Threading.Channels;
using BackgroundQueueService;
var builder = WebApplication.CreateBuilder(args);
// The max memory to use for the upload endpoint on this instance.
var maxMemory = 500 * 1024 * 1024;
// The max size of a single message, staying below the default LOH size of 85K.
var maxMessageSize = 80 * 1024;
// The max size of the queue based on those restrictions
var maxQueueSize = maxMemory / maxMessageSize;
// Create a channel to send data to the background queue.
builder.Services.AddSingleton<Channel<ReadOnlyMemory<byte>>>((_) =>
Channel.CreateBounded<ReadOnlyMemory<byte>>(maxQueueSize));
// Create a background queue service.
builder.Services.AddHostedService<BackgroundQueue>();
var app = builder.Build();
// curl --request POST 'https://localhost:<port>/register' --header 'Content-Type: application/json' --data-raw '{ "Name":"Samson", "Age": 23, "Country":"Nigeria" }'
// curl --request POST "https://localhost:<port>/register" --header "Content-Type: application/json" --data-raw "{ \"Name\":\"Samson\", \"Age\": 23, \"Country\":\"Nigeria\" }"
app.MapPost("/register", async (HttpRequest req, Stream body,
Channel<ReadOnlyMemory<byte>> queue) =>
{
if (req.ContentLength is not null && req.ContentLength > maxMessageSize)
{
return Results.BadRequest();
}
// We're not above the message size and we have a content length, or
// we're a chunked request and we're going to read up to the maxMessageSize + 1.
// We add one to the message size so that we can detect when a chunked request body
// is bigger than our configured max.
var readSize = (int?)req.ContentLength ?? (maxMessageSize + 1);
var buffer = new byte[readSize];
// Read at least that many bytes from the body.
var read = await body.ReadAtLeastAsync(buffer, readSize, throwOnEndOfStream: false);
// We read more than the max, so this is a bad request.
if (read > maxMessageSize)
{
return Results.BadRequest();
}
// Attempt to send the buffer to the background queue.
if (queue.Writer.TryWrite(buffer.AsMemory(0..read)))
{
return Results.Accepted();
}
// We couldn't accept the message since we're overloaded.
return Results.StatusCode(StatusCodes.Status429TooManyRequests);
});
app.Run();
- Verileri okurken,
Stream
ile aynı nesnedirHttpRequest.Body
. - İstek gövdesi varsayılan olarak arabelleğe alınmıyor. Ceset okunduktan sonra geri alınamaz. Akış birden çok kez okunamaz.
Stream
PipeReader
ve, temel alınan arabellekler atılacağı veya yeniden kullanılacağı için en düşük eylem işleyicisi dışında kullanılamaz.
IFormFile ve IFormFileCollection kullanılarak dosya yüklemeleri
Aşağıdaki kod dosyayı karşıya yüklemek için ve IFormFileCollection kullanırIFormFile:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapPost("/upload", async (IFormFile file) =>
{
var tempFile = Path.GetTempFileName();
app.Logger.LogInformation(tempFile);
using var stream = File.OpenWrite(tempFile);
await file.CopyToAsync(stream);
});
app.MapPost("/upload_many", async (IFormFileCollection myFiles) =>
{
foreach (var file in myFiles)
{
var tempFile = Path.GetTempFileName();
app.Logger.LogInformation(tempFile);
using var stream = File.OpenWrite(tempFile);
await file.CopyToAsync(stream);
}
});
app.Run();
Kimliği doğrulanmış dosya yükleme istekleri Yetkilendirme üst bilgisi, istemci sertifikası veya cookie üst bilgi kullanılarak desteklenir.
ASP.NET Core 7.0'da antiforgery için yerleşik destek yoktur. Antiforgery, ASP.NET Core 8.0 ve sonraki sürümlerde kullanılabilir. Ancak, hizmeti kullanılarak IAntiforgery
uygulanabilir.
Üst bilgilerden ve sorgu dizelerinden dizileri ve dize değerlerini bağlama
Aşağıdaki kod, sorgu dizelerini ilkel türler, dize dizileri ve StringValues dizilerine bağlamayı gösterir:
// Bind query string values to a primitive type array.
// GET /tags?q=1&q=2&q=3
app.MapGet("/tags", (int[] q) =>
$"tag1: {q[0]} , tag2: {q[1]}, tag3: {q[2]}");
// Bind to a string array.
// GET /tags2?names=john&names=jack&names=jane
app.MapGet("/tags2", (string[] names) =>
$"tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}");
// Bind to StringValues.
// GET /tags3?names=john&names=jack&names=jane
app.MapGet("/tags3", (StringValues names) =>
$"tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}");
Sorgu dizelerini veya üst bilgi değerlerini karmaşık türlerden oluşan bir diziye bağlama, tür TryParse
uygulandığında desteklenir. Aşağıdaki kod bir dize dizisine bağlanır ve belirtilen etiketlere sahip tüm öğeleri döndürür:
// GET /todoitems/tags?tags=home&tags=work
app.MapGet("/todoitems/tags", async (Tag[] tags, TodoDb db) =>
{
return await db.Todos
.Where(t => tags.Select(i => i.Name).Contains(t.Tag.Name))
.ToListAsync();
});
Aşağıdaki kod modeli ve gerekli TryParse
uygulamayı gösterir:
public class Todo
{
public int Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
// This is an owned entity.
public Tag Tag { get; set; } = new();
}
[Owned]
public class Tag
{
public string? Name { get; set; } = "n/a";
public static bool TryParse(string? name, out Tag tag)
{
if (name is null)
{
tag = default!;
return false;
}
tag = new Tag { Name = name };
return true;
}
}
Aşağıdaki kod bir int
diziye bağlanır:
// GET /todoitems/query-string-ids?ids=1&ids=3
app.MapGet("/todoitems/query-string-ids", async (int[] ids, TodoDb db) =>
{
return await db.Todos
.Where(t => ids.Contains(t.Id))
.ToListAsync();
});
Yukarıdaki kodu test etmek için aşağıdaki uç noktayı ekleyerek veritabanını öğelerle Todo
doldurun:
// POST /todoitems/batch
app.MapPost("/todoitems/batch", async (Todo[] todos, TodoDb db) =>
{
await db.Todos.AddRangeAsync(todos);
await db.SaveChangesAsync();
return Results.Ok(todos);
});
Aşağıdaki verileri önceki uç noktaya geçirmek gibi HttpRepl
bir API test aracı kullanın:
[
{
"id": 1,
"name": "Have Breakfast",
"isComplete": true,
"tag": {
"name": "home"
}
},
{
"id": 2,
"name": "Have Lunch",
"isComplete": true,
"tag": {
"name": "work"
}
},
{
"id": 3,
"name": "Have Supper",
"isComplete": true,
"tag": {
"name": "home"
}
},
{
"id": 4,
"name": "Have Snacks",
"isComplete": true,
"tag": {
"name": "N/A"
}
}
]
Aşağıdaki kod üst bilgi anahtarına X-Todo-Id
bağlanır ve eşleşen Id
değerlere Todo
sahip öğeleri döndürür:
// GET /todoitems/header-ids
// The keys of the headers should all be X-Todo-Id with different values
app.MapGet("/todoitems/header-ids", async ([FromHeader(Name = "X-Todo-Id")] int[] ids, TodoDb db) =>
{
return await db.Todos
.Where(t => ids.Contains(t.Id))
.ToListAsync();
});
Not
Sorgu dizesinden bir string[]
bağlama yapılırken eşleşen sorgu dizesi değerinin olmaması, null değer yerine boş bir diziyle sonuçlanır.
[AsParameters] ile bağımsız değişken listeleri için parametre bağlama
AsParametersAttribute karmaşık veya özyinelemeli model bağlamasına değil, türlere basit parametre bağlamasını etkinleştirir.
Aşağıdaki kodu inceleyin:
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
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());
// Remaining code removed for brevity.
Aşağıdaki GET
uç noktayı göz önünde bulundurun:
app.MapGet("/todoitems/{id}",
async (int Id, TodoDb Db) =>
await Db.Todos.FindAsync(Id)
is Todo todo
? Results.Ok(new TodoItemDTO(todo))
: Results.NotFound());
struct
Aşağıdakiler, önceki vurgulanan parametreleri değiştirmek için kullanılabilir:
struct TodoItemRequest
{
public int Id { get; set; }
public TodoDb Db { get; set; }
}
Yeniden düzenlenmiş GET
uç nokta, AsParameters özniteliğiyle öncekini struct
kullanır:
app.MapGet("/ap/todoitems/{id}",
async ([AsParameters] TodoItemRequest request) =>
await request.Db.Todos.FindAsync(request.Id)
is Todo todo
? Results.Ok(new TodoItemDTO(todo))
: Results.NotFound());
Aşağıdaki kod, uygulamadaki ek uç noktaları gösterir:
app.MapPost("/todoitems", async (TodoItemDTO Dto, TodoDb Db) =>
{
var todoItem = new Todo
{
IsComplete = Dto.IsComplete,
Name = Dto.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 Dto, TodoDb Db) =>
{
var todo = await Db.Todos.FindAsync(Id);
if (todo is null) return Results.NotFound();
todo.Name = Dto.Name;
todo.IsComplete = Dto.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.Ok(new TodoItemDTO(todo));
}
return Results.NotFound();
});
Parametre listelerini yeniden düzenlemede aşağıdaki sınıflar kullanılır:
class CreateTodoItemRequest
{
public TodoItemDTO Dto { get; set; } = default!;
public TodoDb Db { get; set; } = default!;
}
class EditTodoItemRequest
{
public int Id { get; set; }
public TodoItemDTO Dto { get; set; } = default!;
public TodoDb Db { get; set; } = default!;
}
Aşağıdaki kod, ve önceki struct
ve sınıflarını kullanarak AsParameters
yeniden düzenlenmiş uç noktaları gösterir:
app.MapPost("/ap/todoitems", async ([AsParameters] CreateTodoItemRequest request) =>
{
var todoItem = new Todo
{
IsComplete = request.Dto.IsComplete,
Name = request.Dto.Name
};
request.Db.Todos.Add(todoItem);
await request.Db.SaveChangesAsync();
return Results.Created($"/todoitems/{todoItem.Id}", new TodoItemDTO(todoItem));
});
app.MapPut("/ap/todoitems/{id}", async ([AsParameters] EditTodoItemRequest request) =>
{
var todo = await request.Db.Todos.FindAsync(request.Id);
if (todo is null) return Results.NotFound();
todo.Name = request.Dto.Name;
todo.IsComplete = request.Dto.IsComplete;
await request.Db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/ap/todoitems/{id}", async ([AsParameters] TodoItemRequest request) =>
{
if (await request.Db.Todos.FindAsync(request.Id) is Todo todo)
{
request.Db.Todos.Remove(todo);
await request.Db.SaveChangesAsync();
return Results.Ok(new TodoItemDTO(todo));
}
return Results.NotFound();
});
Yukarıdaki parametreleri değiştirmek için aşağıdaki record
türler kullanılabilir:
record TodoItemRequest(int Id, TodoDb Db);
record CreateTodoItemRequest(TodoItemDTO Dto, TodoDb Db);
record EditTodoItemRequest(int Id, TodoItemDTO Dto, TodoDb Db);
struct
ile AsParameters
kullanmak, tür kullanmaktan record
daha yüksek performansa sahip olabilir.
AspNetCore.Docs.Samples deposundaki tam örnek kod.
Özel Bağlama
Parametre bağlamasını özelleştirmenin iki yolu vardır:
- Yol, sorgu ve üst bilgi bağlama kaynakları için, türü için statik
TryParse
bir yöntem ekleyerek özel türleri bağlayın. - Bir türe bir
BindAsync
yöntem uygulayarak bağlama işlemini denetleyin.
TryParse
TryParse
iki API'ye sahiptir:
public static bool TryParse(string value, out T result);
public static bool TryParse(string value, IFormatProvider provider, out T result);
Aşağıdaki kod URI /map?Point=12.3,10.1
ile birlikte görüntülenirPoint: 12.3, 10.1
:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// GET /map?Point=12.3,10.1
app.MapGet("/map", (Point point) => $"Point: {point.X}, {point.Y}");
app.Run();
public class Point
{
public double X { get; set; }
public double Y { get; set; }
public static bool TryParse(string? value, IFormatProvider? provider,
out Point? point)
{
// Format is "(12.3,10.1)"
var trimmedValue = value?.TrimStart('(').TrimEnd(')');
var segments = trimmedValue?.Split(',',
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (segments?.Length == 2
&& double.TryParse(segments[0], out var x)
&& double.TryParse(segments[1], out var y))
{
point = new Point { X = x, Y = y };
return true;
}
point = null;
return false;
}
}
BindAsync
BindAsync
aşağıdaki API'lere sahiptir:
public static ValueTask<T?> BindAsync(HttpContext context, ParameterInfo parameter);
public static ValueTask<T?> BindAsync(HttpContext context);
Aşağıdaki kod URI /products?SortBy=xyz&SortDir=Desc&Page=99
ile birlikte görüntülenirSortBy:xyz, SortDirection:Desc, CurrentPage:99
:
using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// GET /products?SortBy=xyz&SortDir=Desc&Page=99
app.MapGet("/products", (PagingData pageData) => $"SortBy:{pageData.SortBy}, " +
$"SortDirection:{pageData.SortDirection}, CurrentPage:{pageData.CurrentPage}");
app.Run();
public class PagingData
{
public string? SortBy { get; init; }
public SortDirection SortDirection { get; init; }
public int CurrentPage { get; init; } = 1;
public static ValueTask<PagingData?> BindAsync(HttpContext context,
ParameterInfo parameter)
{
const string sortByKey = "sortBy";
const string sortDirectionKey = "sortDir";
const string currentPageKey = "page";
Enum.TryParse<SortDirection>(context.Request.Query[sortDirectionKey],
ignoreCase: true, out var sortDirection);
int.TryParse(context.Request.Query[currentPageKey], out var page);
page = page == 0 ? 1 : page;
var result = new PagingData
{
SortBy = context.Request.Query[sortByKey],
SortDirection = sortDirection,
CurrentPage = page
};
return ValueTask.FromResult<PagingData?>(result);
}
}
public enum SortDirection
{
Default,
Asc,
Desc
}
Bağlama hataları
Bağlama başarısız olduğunda, çerçeve hata ayıklama iletisini günlüğe kaydeder ve hata moduna bağlı olarak istemciye çeşitli durum kodları döndürür.
Hata modu | Null Atanabilir Parametre Türü | Bağlama Kaynağı | Durum kodu |
---|---|---|---|
{ParameterType}.TryParse Döndürür false |
evet | route/query/header | 400 |
{ParameterType}.BindAsync Döndürür null |
evet | özel | 400 |
{ParameterType}.BindAsync Atar |
önemli değil | özel | 500 |
JSON gövdesinin seri durumdan çıkarılamaması | önemli değil | gövde | 400 |
Yanlış içerik türü (değil application/json ) |
önemli değil | gövde | Kategori 415 |
Bağlama Önceliği
Bir parametreden bağlama kaynağını belirleme kuralları:
- Parametrede (From* öznitelikleri) aşağıdaki sırayla tanımlanan açık öznitelik:
- Yol değerleri:
[FromRoute]
- Sorgu dizesi:
[FromQuery]
- Üstbilgi:
[FromHeader]
- Beden:
[FromBody]
- Hizmet:
[FromServices]
- Parametre değerleri:
[AsParameters]
- Yol değerleri:
- Özel türler
HttpContext
HttpRequest
(HttpContext.Request
)HttpResponse
(HttpContext.Response
)ClaimsPrincipal
(HttpContext.User
)CancellationToken
(HttpContext.RequestAborted
)IFormFileCollection
(HttpContext.Request.Form.Files
)IFormFile
(HttpContext.Request.Form.Files[paramName]
)Stream
(HttpContext.Request.Body
)PipeReader
(HttpContext.Request.BodyReader
)
- Parametre türü geçerli bir statik
BindAsync
yönteme sahiptir. - Parametre türü bir dizedir veya geçerli bir statik
TryParse
yöntemi vardır.- Rota şablonunda parametre adı varsa.
id
içindeapp.Map("/todo/{id}", (int id) => {});
, yolundan bağlıdır. - Sorgu dizesinden bağlanır.
- Rota şablonunda parametre adı varsa.
- Parametre türü bağımlılık ekleme tarafından sağlanan bir hizmetse, kaynak olarak bu hizmeti kullanır.
- parametresi gövdedendir.
Gövde bağlaması için JSON seri durumdan çıkarma seçeneklerini yapılandırma
Gövde bağlama kaynağı seri durumdan çıkarma için kullanır System.Text.Json . Bu varsayılanı değiştirmek mümkün değildir, ancak JSON serileştirme ve seri durumdan çıkarma seçenekleri yapılandırılabilir.
JSON seri durumdan çıkarma seçeneklerini genel olarak yapılandırma
Bir uygulama için genel olarak geçerli olan seçenekler çağrılarak ConfigureHttpJsonOptionsyapılandırılabilir. Aşağıdaki örnek, ortak alanları ve JSON çıkışını biçimlendirmektedir.
var builder = WebApplication.CreateBuilder(args);
builder.Services.ConfigureHttpJsonOptions(options => {
options.SerializerOptions.WriteIndented = true;
options.SerializerOptions.IncludeFields = true;
});
var app = builder.Build();
app.MapPost("/", (Todo todo) => {
if (todo is not null) {
todo.Name = todo.NameField;
}
return todo;
});
app.Run();
class Todo {
public string? Name { get; set; }
public string? NameField;
public bool IsComplete { get; set; }
}
// If the request body contains the following JSON:
//
// {"nameField":"Walk dog", "isComplete":false}
//
// The endpoint returns the following JSON:
//
// {
// "name":"Walk dog",
// "nameField":"Walk dog",
// "isComplete":false
// }
Örnek kod hem serileştirmeyi hem de seri durumdan çıkarmayı yapılandırdığından çıktı JSON'unu okuyabilir NameField
ve içerebilir NameField
.
Uç nokta için JSON seri durumdan çıkarma seçeneklerini yapılandırma
ReadFromJsonAsync bir nesneyi kabul JsonSerializerOptions eden aşırı yüklemelere sahiptir. Aşağıdaki örnek, ortak alanları ve JSON çıkışını biçimlendirmektedir.
using System.Text.Json;
var app = WebApplication.Create();
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web) {
IncludeFields = true,
WriteIndented = true
};
app.MapPost("/", async (HttpContext context) => {
if (context.Request.HasJsonContentType()) {
var todo = await context.Request.ReadFromJsonAsync<Todo>(options);
if (todo is not null) {
todo.Name = todo.NameField;
}
return Results.Ok(todo);
}
else {
return Results.BadRequest();
}
});
app.Run();
class Todo
{
public string? Name { get; set; }
public string? NameField;
public bool IsComplete { get; set; }
}
// If the request body contains the following JSON:
//
// {"nameField":"Walk dog", "isComplete":false}
//
// The endpoint returns the following JSON:
//
// {
// "name":"Walk dog",
// "isComplete":false
// }
Yukarıdaki kod özelleştirilmiş seçenekleri yalnızca seri durumdan çıkarma işlemine uyguladığından çıktı JSON dışlar NameField
.
İstek gövdesini okuma
bir veya HttpRequest parametresini kullanarak HttpContext istek gövdesini doğrudan okuyun:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/uploadstream", async (IConfiguration config, HttpRequest request) =>
{
var filePath = Path.Combine(config["StoredFilesPath"], Path.GetRandomFileName());
await using var writeStream = File.Create(filePath);
await request.BodyReader.CopyToAsync(writeStream);
});
app.Run();
Yukarıdaki kod:
- kullanarak HttpRequest.BodyReaderistek gövdesine erişir.
- İstek gövdesini yerel bir dosyaya kopyalar.
Yanıtlar
Yol işleyicileri aşağıdaki dönüş değer türlerini destekler:
IResult
based - Buna ve dahildirTask<IResult>
ValueTask<IResult>
string
- Buna ve dahildirTask<string>
ValueTask<string>
T
(Başka herhangi bir tür) - Buna ve dahildirTask<T>
ValueTask<T>
İşleyici dönüş değerlerini yönlendirmeye yönelik daha ayrıntılı bir kılavuz için bkz. Minimal API uygulamalarında yanıt oluşturma
Örnek dönüş değerleri
dize dönüş değerleri
app.MapGet("/hello", () => "Hello World");
JSON dönüş değerleri
app.MapGet("/hello", () => new { Message = "Hello World" });
Dönüş TypedResults
Aşağıdaki kod bir TypedResultsdöndürür:
app.MapGet("/hello", () => TypedResults.Ok(new Message() { Text = "Hello World!" }));
dönüş TypedResults
, döndürmek Resultsiçin tercih edilir. Daha fazla bilgi için bkz . TypedResults vs Results.
IResult dönüş değerleri
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Aşağıdaki örnek, yanıtı özelleştirmek için yerleşik sonuç türlerini kullanır:
app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound())
.Produces<Todo>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
JSON
app.MapGet("/hello", () => Results.Json(new { Message = "Hello World" }));
Özel Durum Kodu
app.MapGet("/405", () => Results.StatusCode(405));
Metin
app.MapGet("/text", () => Results.Text("This is some text"));
Akış
var proxyClient = new HttpClient();
app.MapGet("/pokemon", async () =>
{
var stream = await proxyClient.GetStreamAsync("http://contoso/pokedex.json");
// Proxy the response as JSON
return Results.Stream(stream, "application/json");
});
Daha fazla örnek için bkz . Minimal API uygulamalarında yanıt oluşturma.
Yönlendir
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
Dosya
app.MapGet("/download", () => Results.File("myfile.text"));
Yerleşik sonuçlar
ve statik sınıflarında Results TypedResults ortak sonuç yardımcıları vardır. dönüş TypedResults
, döndürmek Results
için tercih edilir. Daha fazla bilgi için bkz . TypedResults vs Results.
Sonuçları özelleştirme
Uygulamalar özel IResult bir tür uygulayarak yanıtları denetleyebilir. Aşağıdaki kod, BIR HTML sonuç türü örneğidir:
using System.Net.Mime;
using System.Text;
static class ResultsExtensions
{
public static IResult Html(this IResultExtensions resultExtensions, string html)
{
ArgumentNullException.ThrowIfNull(resultExtensions);
return new HtmlResult(html);
}
}
class HtmlResult : IResult
{
private readonly string _html;
public HtmlResult(string html)
{
_html = html;
}
public Task ExecuteAsync(HttpContext httpContext)
{
httpContext.Response.ContentType = MediaTypeNames.Text.Html;
httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(_html);
return httpContext.Response.WriteAsync(_html);
}
}
Bu özel sonuçları daha bulunabilir hale getirmek için öğesine Microsoft.AspNetCore.Http.IResultExtensions bir uzantı yöntemi eklemenizi öneririz.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/html", () => Results.Extensions.Html(@$"<!doctype html>
<html>
<head><title>miniHTML</title></head>
<body>
<h1>Hello World</h1>
<p>The time on the server is {DateTime.Now:O}</p>
</body>
</html>"));
app.Run();
Yazılan sonuçlar
Arabirim, IResult döndürülen nesneyi HTTP yanıtına seri hale getirmek için JSON örtük desteğini kullanmayan en düşük API'lerden döndürülen değerleri temsil edebilir. Statik Results sınıfı, farklı yanıt türlerini temsil eden farklı IResult
nesneler oluşturmak için kullanılır. Örneğin, yanıt durum kodunu ayarlama veya başka bir URL'ye yönlendirme.
Uygulayan IResult
türler geneldir ve test sırasında tür onaylarına izin verir. Örneğin:
[TestClass()]
public class WeatherApiTests
{
[TestMethod()]
public void MapWeatherApiTest()
{
var result = WeatherApi.GetAllWeathers();
Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
}
}
Statik TypedResults sınıfında karşılık gelen yöntemlerin dönüş türlerine bakarak, kullanılacak doğru genel IResult
türü bulabilirsiniz.
Daha fazla örnek için bkz . Minimal API uygulamalarında yanıt oluşturma.
Filtreler
Bkz. Minimum API uygulamalarında filtreler
Yetkilendirme
Yollar yetkilendirme ilkeleri kullanılarak korunabilir. Bunlar özniteliği aracılığıyla [Authorize]
veya yöntemi kullanılarak RequireAuthorization bildirilebilir:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebRPauth.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization(o => o.AddPolicy("AdminsOnly",
b => b.RequireClaim("admin", "true")));
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
var app = builder.Build();
app.UseAuthorization();
app.MapGet("/auth", [Authorize] () => "This endpoint requires authorization.");
app.MapGet("/", () => "This endpoint doesn't require authorization.");
app.MapGet("/Identity/Account/Login", () => "Sign in page at this endpoint.");
app.Run();
Yukarıdaki kod ile RequireAuthorizationyazılabilir:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Aşağıdaki örnekte ilke tabanlı yetkilendirme kullanılmaktadır:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebRPauth.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization(o => o.AddPolicy("AdminsOnly",
b => b.RequireClaim("admin", "true")));
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
var app = builder.Build();
app.UseAuthorization();
app.MapGet("/admin", [Authorize("AdminsOnly")] () =>
"The /admin endpoint is for admins only.");
app.MapGet("/admin2", () => "The /admin2 endpoint is for admins only.")
.RequireAuthorization("AdminsOnly");
app.MapGet("/", () => "This endpoint doesn't require authorization.");
app.MapGet("/Identity/Account/Login", () => "Sign in page at this endpoint.");
app.Run();
Kimliği doğrulanmamış kullanıcıların bir uç noktaya erişmesine izin verme
kimliği [AllowAnonymous]
doğrulanmamış kullanıcıların uç noktalara erişmesine izin verir:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Yollar CORS ilkeleri kullanılarak CORS etkinleştirilebilir. CORS, özniteliği veya [EnableCors]
yöntemi kullanılarak RequireCors bildirilebilir. Aşağıdaki örnekler CORS'yi etkinleştirir:
const string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
var app = builder.Build();
app.UseCors();
app.MapGet("/",() => "Hello CORS!");
app.Run();
using Microsoft.AspNetCore.Cors;
const string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
var app = builder.Build();
app.UseCors();
app.MapGet("/cors", [EnableCors(MyAllowSpecificOrigins)] () =>
"This endpoint allows cross origin requests!");
app.MapGet("/cors2", () => "This endpoint allows cross origin requests!")
.RequireCors(MyAllowSpecificOrigins);
app.Run();
Daha fazla bilgi için bkz . ASP.NET Core'da Çıkış Noktaları Arası İstekleri (CORS) Etkinleştirme
Ayrıca bkz.
Bu belge:
- En düşük API'ler için hızlı başvuru sağlar.
- Deneyimli geliştiricilere yöneliktir. Giriş için bkz . Öğretici: ASP.NET Core ile minimum API oluşturma
En düşük API'ler şunlardan oluşur:
- WebApplication ve WebApplicationBuilder
- Yol işleyicileri
WebApplication
Aşağıdaki kod bir ASP.NET Core şablonu tarafından oluşturulur:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Yukarıdaki kod, komut satırında veya Visual Studio'da Boş Web şablonu seçerek oluşturulabilir dotnet new web
.
Aşağıdaki kod, açıkça oluşturmadan bir WebApplication WebApplicationBuilder(app
) oluşturur:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create
önceden yapılandırılmış varsayılanlarla sınıfının yeni bir örneğini WebApplication başlatır.
Bağlantı noktalarıyla çalışma
Visual Studio veya dotnet new
ile bir web uygulaması oluşturulduğunda, uygulamanın yanıt verdiği bağlantı noktalarını belirten bir Properties/launchSettings.json
dosya oluşturulur. Sonraki bağlantı noktası ayarı örneklerinde, uygulamayı Visual Studio'dan çalıştırmak bir hata iletişim kutusu Unable to connect to web server 'AppName'
döndürür. Komut satırından örnekleri değiştirerek aşağıdaki bağlantı noktasını çalıştırın.
Aşağıdaki bölümlerde uygulamanın yanıt verdiği bağlantı noktası ayarlanır.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
Önceki kodda uygulama bağlantı noktasına 3000
yanıt verir.
Birden çok bağlantı noktası
Aşağıdaki kodda uygulama ve 4000
bağlantı noktasına 3000
yanıt verir.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
Komut satırından bağlantı noktasını ayarlama
Aşağıdaki komut, uygulamanın bağlantı noktasına 7777
yanıt vermesini sağlar:
dotnet run --urls="https://localhost:7777"
Kestrel Uç nokta dosyada appsettings.json
da yapılandırılmışsa, appsettings.json
belirtilen dosya URL'si kullanılır. Daha fazla bilgi için bkz. Kestrel uç nokta yapılandırması
Bağlantı noktasını ortamdan okuma
Aşağıdaki kod, bağlantı noktasını ortamdan okur:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
Bağlantı noktasını ortamdan ayarlamanın tercih edilen yolu, aşağıdaki bölümde gösterilen ortam değişkenini kullanmaktır ASPNETCORE_URLS
.
ASPNETCORE_URLS ortam değişkeni aracılığıyla bağlantı noktalarını ayarlama
Ortam ASPNETCORE_URLS
değişkeni, bağlantı noktasını ayarlamak için kullanılabilir:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS
birden çok URL'leri destekler:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
Tüm arabirimlerde dinleme
Aşağıdaki örneklerde tüm arabirimlerde dinleme gösterilmektedir
http://*:3000
var app = WebApplication.Create(args);
app.Urls.Add("http://*:3000");
app.MapGet("/", () => "Hello World");
app.Run();
http://+:3000
var app = WebApplication.Create(args);
app.Urls.Add("http://+:3000");
app.MapGet("/", () => "Hello World");
app.Run();
http://0.0.0.0:3000
var app = WebApplication.Create(args);
app.Urls.Add("http://0.0.0.0:3000");
app.MapGet("/", () => "Hello World");
app.Run();
ASPNETCORE_URLS kullanarak tüm arabirimlerde dinleme
Önceki örnekler kullanabilir ASPNETCORE_URLS
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
Geliştirme sertifikası ile HTTPS belirtme
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Geliştirme sertifikası hakkında daha fazla bilgi için bkz . Windows ve macOS'ta ASP.NET Core HTTPS geliştirme sertifikasına güvenme.
Özel sertifika kullanarak HTTPS belirtme
Aşağıdaki bölümlerde, dosyayı kullanarak ve yapılandırma yoluyla özel sertifikanın nasıl belirtileceğini gösterilmektedir appsettings.json
.
Ile özel sertifikayı belirtin appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Yapılandırma aracılığıyla özel sertifikayı belirtme
var builder = WebApplication.CreateBuilder(args);
// Configure the cert and the key
builder.Configuration["Kestrel:Certificates:Default:Path"] = "cert.pem";
builder.Configuration["Kestrel:Certificates:Default:KeyPath"] = "key.pem";
var app = builder.Build();
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Sertifika API'lerini kullanma
using System.Security.Cryptography.X509Certificates;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
options.ConfigureHttpsDefaults(httpsOptions =>
{
var certPath = Path.Combine(builder.Environment.ContentRootPath, "cert.pem");
var keyPath = Path.Combine(builder.Environment.ContentRootPath, "key.pem");
httpsOptions.ServerCertificate = X509Certificate2.CreateFromPemFile(certPath,
keyPath);
});
});
var app = builder.Build();
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Ortamı okuma
var app = WebApplication.Create(args);
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/oops");
}
app.MapGet("/", () => "Hello World");
app.MapGet("/oops", () => "Oops! An error happened.");
app.Run();
Ortamı kullanma hakkında daha fazla bilgi için bkz . ASP.NET Core'da birden çok ortam kullanma
Yapılandırma
Aşağıdaki kod yapılandırma sisteminden okunur:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Hello";
app.MapGet("/", () => message);
app.Run();
Daha fazla bilgi için bkz . ASP.NET Core'da yapılandırma
Günlük Kaydı
Aşağıdaki kod, oturum açma uygulaması başlatma işlemine bir ileti yazar:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
Daha fazla bilgi için bkz . .NET Core ve ASP.NET Core'da oturum açma
Bağımlılık Ekleme (DI) kapsayıcıya erişme
Aşağıdaki kod, uygulama başlatma sırasında DI kapsayıcısından hizmet almayı gösterir:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddScoped<SampleService>();
var app = builder.Build();
app.MapControllers();
using (var scope = app.Services.CreateScope())
{
var sampleService = scope.ServiceProvider.GetRequiredService<SampleService>();
sampleService.DoSomething();
}
app.Run();
Daha fazla bilgi için, bkz. ASP.NET Core'de bağımlılık ekleme.
WebApplicationBuilder
Bu bölüm, kullanan WebApplicationBuilderörnek kodu içerir.
İçerik kökünü, uygulama adını ve ortamı değiştirme
Aşağıdaki kod içerik kökünü, uygulama adını ve ortamı ayarlar:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
ApplicationName = typeof(Program).Assembly.FullName,
ContentRootPath = Directory.GetCurrentDirectory(),
EnvironmentName = Environments.Staging,
WebRootPath = "customwwwroot"
});
Console.WriteLine($"Application Name: {builder.Environment.ApplicationName}");
Console.WriteLine($"Environment Name: {builder.Environment.EnvironmentName}");
Console.WriteLine($"ContentRoot Path: {builder.Environment.ContentRootPath}");
Console.WriteLine($"WebRootPath: {builder.Environment.WebRootPath}");
var app = builder.Build();
WebApplication.CreateBuilder önceden yapılandırılmış varsayılanlarla WebApplicationBuilder sınıfının yeni bir örneğini başlatır.
Daha fazla bilgi için bkz . ASP.NET Temel bilgilere genel bakış
İçerik kökünü, uygulama adını ve ortamı ortam değişkenlerine veya komut satırına göre değiştirme
Aşağıdaki tabloda içerik kökünü, uygulama adını ve ortamı değiştirmek için kullanılan ortam değişkeni ve komut satırı bağımsız değişkeni gösterilmektedir:
özelliği | Ortam değişkeni | Komut satırı bağımsız değişkeni |
---|---|---|
Uygulama adı | ASPNETCORE_APPLICATIONNAME | --applicationName |
Ortam adı | ASPNETCORE_ENVIRONMENT | --çevre |
İçerik kökü | ASPNETCORE_CONTENTROOT | --contentRoot |
Yapılandırma sağlayıcıları ekleme
Aşağıdaki örnek INI yapılandırma sağlayıcısını ekler:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Ayrıntılı bilgi için bkz. ASP.NET Core'da Yapılandırma bölümünde dosya yapılandırma sağlayıcıları.
Yapılandırmayı okuma
Varsayılan olarak WebApplicationBuilder , yapılandırmayı aşağıdakiler dahil olmak üzere birden çok kaynaktan okur:
appSettings.json
veappSettings.{environment}.json
- Ortam değişkenleri
- Komut satırı
Okunan yapılandırma kaynaklarının tam listesi için bkz. ASP.NET Core'da Yapılandırma'da varsayılan yapılandırma
Aşağıdaki kod yapılandırmadan okur HelloKey
ve değeri uç noktada görüntüler /
. Yapılandırma değeri null ise , "Hello" öğesine message
atanır:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
Ortamı okuma
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
Günlük sağlayıcıları ekleme
var builder = WebApplication.CreateBuilder(args);
// Configure JSON logging to the console.
builder.Logging.AddJsonConsole();
var app = builder.Build();
app.MapGet("/", () => "Hello JSON console!");
app.Run();
Hizmet ekleme
var builder = WebApplication.CreateBuilder(args);
// Add the memory cache services.
builder.Services.AddMemoryCache();
// Add a custom scoped service.
builder.Services.AddScoped<ITodoRepository, TodoRepository>();
var app = builder.Build();
IHostBuilder'i özelleştirme
üzerindeki IHostBuilder mevcut uzantı yöntemlerine Host özelliği kullanılarak erişilebilir:
var builder = WebApplication.CreateBuilder(args);
// Wait 30 seconds for graceful shutdown.
builder.Host.ConfigureHostOptions(o => o.ShutdownTimeout = TimeSpan.FromSeconds(30));
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
IWebHostBuilder'i özelleştirme
üzerindeki IWebHostBuilder uzantı yöntemlerine WebApplicationBuilder.WebHost özelliği kullanılarak erişilebilir.
var builder = WebApplication.CreateBuilder(args);
// Change the HTTP server implemenation to be HTTP.sys based
builder.WebHost.UseHttpSys();
var app = builder.Build();
app.MapGet("/", () => "Hello HTTP.sys");
app.Run();
Web kökünü değiştirme
Varsayılan olarak, web kökü klasördeki içerik köküne wwwroot
göredir. Web kökü, statik dosyalar ara yazılımının statik dosyaları ara yazılımının ara yazılım tarafından arandığı yerdir. Web kökü ile, komut satırıyla WebHostOptions
veya yöntemiyle UseWebRoot değiştirilebilir:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Özel bağımlılık ekleme (DI) kapsayıcısı
Aşağıdaki örnekte Autofac kullanılır:
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
// Register services directly with Autofac here. Don't
// call builder.Populate(), that happens in AutofacServiceProviderFactory.
builder.Host.ConfigureContainer<ContainerBuilder>(builder => builder.RegisterModule(new MyApplicationModule()));
var app = builder.Build();
Ara Yazılım Ekle
Mevcut ASP.NET Core ara yazılımları üzerinde WebApplication
yapılandırılabilir:
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
Daha fazla bilgi için bkz . ASP.NET Core Ara Yazılımı
Geliştirici özel durum sayfası
WebApplication.CreateBuilder önceden yapılandırılmış varsayılanlarla sınıfının yeni bir örneğini WebApplicationBuilder başlatır. Geliştirici özel durum sayfası önceden yapılandırılmış varsayılanlarda etkinleştirilir. Geliştirme ortamında aşağıdaki kod çalıştırıldığında, öğesine /
gitmek özel durumu gösteren kolay bir sayfa oluşturur.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () =>
{
throw new InvalidOperationException("Oops, the '/' route has thrown an exception.");
});
app.Run();
ASP.NET Core Ara Yazılımı
Aşağıdaki tabloda en az API ile sık kullanılan ara yazılımlardan bazıları listelanmaktadır.
Ara yazılım | Açıklama | API |
---|---|---|
Kimlik Doğrulaması | Kimlik doğrulaması desteği sağlar. | UseAuthentication |
Yetkilendirme | Yetkilendirme desteği sağlar. | UseAuthorization |
CORS | Çıkış Noktaları Arası Kaynak Paylaşımı'nı yapılandırır. | UseCors |
Özel Durum İşleyicisi | Ara yazılım işlem hattı tarafından oluşan özel durumları genel olarak işler. | UseExceptionHandler |
İletilen Üst Bilgiler | Taşınan üst bilgileri geçerli isteğe iletir. | UseForwardedHeaders |
HTTPS Yeniden Yönlendirme | Tüm HTTP isteklerini HTTPS'ye yönlendirir. | UseHttpsRedirection |
HTTP Katı Aktarım Güvenliği (HSTS) | Özel bir yanıt üst bilgisi ekleyen güvenlik iyileştirme ara yazılımı. | UseHsts |
İstek Günlüğü | HTTP isteklerini ve yanıtlarını günlüğe kaydetme desteği sağlar. | UseHttpLogging |
W3C İstek Günlüğü | HTTP isteklerini ve yanıtlarını W3C biçiminde günlüğe kaydetme desteği sağlar. | UseW3CLogging |
Yanıtları Önbelleğe Alma | Yanıtları önbelleğe almak için destek sağlar. | UseResponseCaching |
Yanıt Sıkıştırma | Yanıtları sıkıştırma desteği sağlar. | UseResponseCompression |
Oturum | Kullanıcı oturumlarını yönetmek için destek sağlar. | UseSession |
Statik Dosyalar | Statik dosyalara ve dizine göz atma desteği sağlar. | UseStaticFiles, UseFileServer |
WebSockets | WebSockets protokolünü etkinleştirir. | UseWebSockets |
İstek işleme
Aşağıdaki bölümlerde yönlendirme, parametre bağlama ve yanıtlar ele alınıyor.
Yönlendirme
Yapılandırılmış WebApplication
bir destek Map{Verb}
ve MapMethodsdestekler:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "This is a GET");
app.MapPost("/", () => "This is a POST");
app.MapPut("/", () => "This is a PUT");
app.MapDelete("/", () => "This is a DELETE");
app.MapMethods("/options-or-head", new[] { "OPTIONS", "HEAD" },
() => "This is an options or head request ");
app.Run();
Yol İşleyicileri
Yol işleyicileri, yol eşleştiğinde yürütülen yöntemlerdir. Yol işleyicileri, zaman uyumlu veya zaman uyumsuz dahil olmak üzere herhangi bir şeklin işlevi olabilir. Yol işleyicileri bir lambda ifadesi, yerel bir işlev, örnek yöntemi veya statik bir yöntem olabilir.
Lambda ifadesi
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/inline", () => "This is an inline lambda");
var handler = () => "This is a lambda variable";
app.MapGet("/", handler);
app.Run();
Yerel işlev
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Örnek yöntemi
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var handler = new HelloHandler();
app.MapGet("/", handler.Hello);
app.Run();
class HelloHandler
{
public string Hello()
{
return "Hello Instance method";
}
}
Statik yöntem
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", HelloHandler.Hello);
app.Run();
class HelloHandler
{
public static string Hello()
{
return "Hello static method";
}
}
Adlandırılmış uç noktalar ve bağlantı oluşturma
Uç noktaya URL'ler oluşturmak için uç noktalara adlar verilebilir. Adlandırılmış uç nokta kullanmak, bir uygulamada yolları sabit kodlamaktan kaçınıyor:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/hello", () => "Hello named route")
.WithName("hi");
app.MapGet("/", (LinkGenerator linker) =>
$"The link to the hello route is {linker.GetPathByName("hi", values: null)}");
app.Run();
Yukarıdaki kod uç noktadan görüntülenir The link to the hello endpoint is /hello
/
.
NOT: Uç nokta adları büyük/küçük harfe duyarlıdır.
Uç nokta adları:
- Genel olarak benzersiz olması gerekir.
- OpenAPI desteği etkinleştirildiğinde OpenAPI işlem kimliği olarak kullanılır. Daha fazla bilgi için bkz . OpenAPI.
Rota Parametreleri
Yol parametreleri, yol deseni tanımının bir parçası olarak yakalanabilir:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/users/{userId}/books/{bookId}",
(int userId, int bookId) => $"The user id is {userId} and book id is {bookId}");
app.Run();
Yukarıdaki kod URI'sinden /users/3/books/7
döndürürThe user id is 3 and book id is 7
.
Yol işleyicisi, yakalanacak parametreleri bildirebilir. Bir istek, yakalamak üzere bildirilen parametrelerle bir yol yapıldığında, parametreler ayrıştırılır ve işleyiciye geçirilir. Bu, değerleri güvenli bir şekilde tür olarak yakalamayı kolaylaştırır. Önceki kodda userId
ve bookId
her ikisi de int
şeklindedir.
Yukarıdaki kodda, herhangi bir yol değeri bir int
'a dönüştürülemezse bir özel durum oluşturulur. GET isteği /users/hello/books/3
aşağıdaki özel durumu oluşturur:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Joker karakter ve tüm yolları yakalama
Aşağıdaki catch all route returns Routing to hello
from the '/posts/hello' endpoint:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Yol kısıtlamaları
Yol kısıtlamaları, bir yolun eşleşen davranışını kısıtlar.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/todos/{id:int}", (int id) => db.Todos.Find(id));
app.MapGet("/todos/{text}", (string text) => db.Todos.Where(t => t.Text.Contains(text)));
app.MapGet("/posts/{slug:regex(^[a-z0-9_-]+$)}", (string slug) => $"Post {slug}");
app.Run();
Aşağıdaki tabloda, önceki yol şablonları ve bunların davranışları gösterilmektedir:
Rota Şablonu | Örnek Eşleşen URI |
---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
Daha fazla bilgi için bkz. ASP.NET Core'da Yönlendirme bölümünde yönlendirme kısıtlaması başvurusu.
Parametre Bağlama
Parametre bağlama, istek verilerini yol işleyicileri tarafından ifade edilen kesin olarak belirlenmiş parametrelere dönüştürme işlemidir. Bağlama kaynağı, parametrelerin nereye bağlandığını belirler. Bağlama kaynakları HTTP yöntemine ve parametre türüne göre açık veya çıkarılabilir.
Desteklenen bağlama kaynakları:
- Yol değerleri
- Sorgu dizesi
- Üst bilgi
- Gövde (JSON olarak)
- Bağımlılık ekleme tarafından sağlanan hizmetler
- Özel
Not
.NET'te form değerlerinden bağlama yerel olarak desteklenmez.
Aşağıdaki örnek GET yol işleyicisi bu parametre bağlama kaynaklarından bazılarını kullanır:
var builder = WebApplication.CreateBuilder(args);
// Added as service
builder.Services.AddSingleton<Service>();
var app = builder.Build();
app.MapGet("/{id}", (int id,
int page,
[FromHeader(Name = "X-CUSTOM-HEADER")] string customHeader,
Service service) => { });
class Service { }
Aşağıdaki tabloda, önceki örnekte kullanılan parametrelerle ilişkili bağlama kaynakları arasındaki ilişki gösterilmektedir.
Parametre | Bağlama Kaynağı |
---|---|
id |
yol değeri |
page |
sorgu dizesi |
customHeader |
üst bilgi |
service |
Bağımlılık ekleme tarafından sağlanır |
, , HEAD
OPTIONS
ve DELETE
HTTP yöntemleri GET
gövdeden örtük olarak bağlanmaz. Bu HTTP yöntemleri için gövdeden (JSON olarak) bağlanmak için ile [FromBody]
açıkça bağlayın veya dosyasından HttpRequestokuyun.
Aşağıdaki örnek POST yol işleyicisi, parametresi için person
bir bağlama gövdesi kaynağı (JSON olarak) kullanır:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/", (Person person) => { });
record Person(string Name, int Age);
Yukarıdaki örneklerde yer alan parametrelerin tümü istek verilerinden otomatik olarak bağlıdır. Parametre bağlamasının sağladığı kolaylığı göstermek için aşağıdaki örnek yol işleyicileri istek verilerini doğrudan istekten nasıl okuyacaklarını gösterir:
app.MapGet("/{id}", (HttpRequest request) =>
{
var id = request.RouteValues["id"];
var page = request.Query["page"];
var customHeader = request.Headers["X-CUSTOM-HEADER"];
// ...
});
app.MapPost("/", async (HttpRequest request) =>
{
var person = await request.ReadFromJsonAsync<Person>();
// ...
});
Açık Parametre Bağlama
Öznitelikler, parametrelerin nereye bağlı olduğunu açıkça bildirmek için kullanılabilir.
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
// Added as service
builder.Services.AddSingleton<Service>();
var app = builder.Build();
app.MapGet("/{id}", ([FromRoute] int id,
[FromQuery(Name = "p")] int page,
[FromServices] Service service,
[FromHeader(Name = "Content-Type")] string contentType)
=> {});
class Service { }
record Person(string Name, int Age);
Parametre | Bağlama Kaynağı |
---|---|
id |
adıyla yol değeri id |
page |
adlı sorgu dizesi "p" |
service |
Bağımlılık ekleme tarafından sağlanır |
contentType |
adıyla üst bilgi "Content-Type" |
Not
.NET'te form değerlerinden bağlama yerel olarak desteklenmez.
DI ile parametre bağlama
En düşük API'ler için parametre bağlama, tür hizmet olarak yapılandırıldığında bağımlılık ekleme yoluyla parametreleri bağlar. Özniteliğin bir parametreye açıkça uygulanması [FromServices]
gerekmez. Aşağıdaki kodda, her iki eylem de saati döndürür:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IDateTime, SystemDateTime>();
var app = builder.Build();
app.MapGet("/", ( IDateTime dateTime) => dateTime.Now);
app.MapGet("/fs", ([FromServices] IDateTime dateTime) => dateTime.Now);
app.Run();
İsteğe bağlı parametreler
Yol işleyicilerinde bildirilen parametreler gerekli olarak değerlendirilir:
- Bir istek yolla eşleşiyorsa, yol işleyicisi yalnızca istekte tüm gerekli parametreler sağlandığında çalışır.
- Tüm gerekli parametrelerin sağlanamaması hatayla sonuçlanır.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int pageNumber) => $"Requesting page {pageNumber}");
app.Run();
URI | result |
---|---|
/products?pageNumber=3 |
3 döndürüldü |
/products |
BadHttpRequestException : Sorgu dizesinden gerekli "int pageNumber" parametresi sağlanmadı. |
/products/1 |
HTTP 404 hatası, eşleşen yol yok |
İsteğe bağlı yapmak pageNumber
için türü isteğe bağlı olarak tanımlayın veya varsayılan bir değer sağlayın:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int? pageNumber) => $"Requesting page {pageNumber ?? 1}");
string ListProducts(int pageNumber = 1) => $"Requesting page {pageNumber}";
app.MapGet("/products2", ListProducts);
app.Run();
URI | result |
---|---|
/products?pageNumber=3 |
3 döndürüldü |
/products |
1 döndürüldü |
/products2 |
1 döndürüldü |
Yukarıdaki null atanabilir ve varsayılan değer tüm kaynaklar için geçerlidir:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/products", (Product? product) => { });
app.Run();
Yukarıdaki kod, istek gövdesi gönderilmezse null bir ürünle yöntemini çağırır.
NOT: Geçersiz veri sağlanırsa ve parametre null atanabilirse, yol işleyicisi çalıştırılmaz .
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int? pageNumber) => $"Requesting page {pageNumber ?? 1}");
app.Run();
URI | result |
---|---|
/products?pageNumber=3 |
3 Döndürülen |
/products |
1 Döndürülen |
/products?pageNumber=two |
BadHttpRequestException : "two" parametresi "Nullable<int> pageNumber" bağlanamadı. |
/products/two |
HTTP 404 hatası, eşleşen yol yok |
Daha fazla bilgi için Bağlama Hataları bölümüne bakın.
Özel türler
Aşağıdaki türler açık öznitelikler olmadan bağlanır:
HttpContext: Geçerli HTTP isteği veya yanıtı hakkındaki tüm bilgileri barındıran bağlam:
app.MapGet("/", (HttpContext context) => context.Response.WriteAsync("Hello World"));
HttpRequest ve HttpResponse: HTTP isteği ve HTTP yanıtı:
app.MapGet("/", (HttpRequest request, HttpResponse response) => response.WriteAsync($"Hello World {request.Query["name"]}"));
CancellationToken: Geçerli HTTP isteğiyle ilişkili iptal belirteci:
app.MapGet("/", async (CancellationToken cancellationToken) => await MakeLongRunningRequestAsync(cancellationToken));
ClaimsPrincipal: İstekle ilişkili kullanıcı, ile HttpContext.Userilişkili:
app.MapGet("/", (ClaimsPrincipal user) => user.Identity.Name);
Özel Bağlama
Parametre bağlamasını özelleştirmenin iki yolu vardır:
- Yol, sorgu ve üst bilgi bağlama kaynakları için, türü için statik
TryParse
bir yöntem ekleyerek özel türleri bağlayın. - Bir türe bir
BindAsync
yöntem uygulayarak bağlama işlemini denetleyin.
TryParse
TryParse
iki API'ye sahiptir:
public static bool TryParse(string value, out T result);
public static bool TryParse(string value, IFormatProvider provider, out T result);
Aşağıdaki kod URI /map?Point=12.3,10.1
ile birlikte görüntülenirPoint: 12.3, 10.1
:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// GET /map?Point=12.3,10.1
app.MapGet("/map", (Point point) => $"Point: {point.X}, {point.Y}");
app.Run();
public class Point
{
public double X { get; set; }
public double Y { get; set; }
public static bool TryParse(string? value, IFormatProvider? provider,
out Point? point)
{
// Format is "(12.3,10.1)"
var trimmedValue = value?.TrimStart('(').TrimEnd(')');
var segments = trimmedValue?.Split(',',
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (segments?.Length == 2
&& double.TryParse(segments[0], out var x)
&& double.TryParse(segments[1], out var y))
{
point = new Point { X = x, Y = y };
return true;
}
point = null;
return false;
}
}
BindAsync
BindAsync
aşağıdaki API'lere sahiptir:
public static ValueTask<T?> BindAsync(HttpContext context, ParameterInfo parameter);
public static ValueTask<T?> BindAsync(HttpContext context);
Aşağıdaki kod URI /products?SortBy=xyz&SortDir=Desc&Page=99
ile birlikte görüntülenirSortBy:xyz, SortDirection:Desc, CurrentPage:99
:
using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// GET /products?SortBy=xyz&SortDir=Desc&Page=99
app.MapGet("/products", (PagingData pageData) => $"SortBy:{pageData.SortBy}, " +
$"SortDirection:{pageData.SortDirection}, CurrentPage:{pageData.CurrentPage}");
app.Run();
public class PagingData
{
public string? SortBy { get; init; }
public SortDirection SortDirection { get; init; }
public int CurrentPage { get; init; } = 1;
public static ValueTask<PagingData?> BindAsync(HttpContext context,
ParameterInfo parameter)
{
const string sortByKey = "sortBy";
const string sortDirectionKey = "sortDir";
const string currentPageKey = "page";
Enum.TryParse<SortDirection>(context.Request.Query[sortDirectionKey],
ignoreCase: true, out var sortDirection);
int.TryParse(context.Request.Query[currentPageKey], out var page);
page = page == 0 ? 1 : page;
var result = new PagingData
{
SortBy = context.Request.Query[sortByKey],
SortDirection = sortDirection,
CurrentPage = page
};
return ValueTask.FromResult<PagingData?>(result);
}
}
public enum SortDirection
{
Default,
Asc,
Desc
}
Bağlama hataları
Bağlama başarısız olduğunda, çerçeve hata ayıklama iletisini günlüğe kaydeder ve hata moduna bağlı olarak istemciye çeşitli durum kodları döndürür.
Hata modu | Null Atanabilir Parametre Türü | Bağlama Kaynağı | Durum kodu |
---|---|---|---|
{ParameterType}.TryParse Döndürür false |
evet | route/query/header | 400 |
{ParameterType}.BindAsync Döndürür null |
evet | özel | 400 |
{ParameterType}.BindAsync Atar |
önemli değil | özel | 500 |
JSON gövdesinin seri durumdan çıkarılamaması | önemli değil | gövde | 400 |
Yanlış içerik türü (değil application/json ) |
önemli değil | gövde | Kategori 415 |
Bağlama Önceliği
Bir parametreden bağlama kaynağını belirleme kuralları:
- Parametrede (From* öznitelikleri) aşağıdaki sırayla tanımlanan açık öznitelik:
- Yol değerleri:
[FromRoute]
- Sorgu dizesi:
[FromQuery]
- Üstbilgi:
[FromHeader]
- Beden:
[FromBody]
- Hizmet:
[FromServices]
- Yol değerleri:
- Özel türler
- Parametre türünün geçerli
BindAsync
bir yöntemi vardır. - Parametre türü bir dizedir veya geçerli
TryParse
bir yöntemi vardır.- Rota şablonunda parametre adı varsa.
id
içindeapp.Map("/todo/{id}", (int id) => {});
, yolundan bağlıdır. - Sorgu dizesinden bağlanır.
- Rota şablonunda parametre adı varsa.
- Parametre türü bağımlılık ekleme tarafından sağlanan bir hizmetse, kaynak olarak bu hizmeti kullanır.
- parametresi gövdedendir.
JSON bağlamayı özelleştirme
Gövde bağlama kaynağı serileştirme için kullanır System.Text.Json . Bu varsayılanı değiştirmek mümkün değildir, ancak bağlama daha önce açıklanan diğer teknikler kullanılarak özelleştirilebilir. JSON seri hale getirici seçeneklerini özelleştirmek için aşağıdakine benzer bir kod kullanın:
using Microsoft.AspNetCore.Http.Json;
var builder = WebApplication.CreateBuilder(args);
// Configure JSON options.
builder.Services.Configure<JsonOptions>(options =>
{
options.SerializerOptions.IncludeFields = true;
});
var app = builder.Build();
app.MapPost("/products", (Product product) => product);
app.Run();
class Product
{
// These are public fields, not properties.
public int Id;
public string? Name;
}
Yukarıdaki kod:
- Hem giriş hem de çıkış varsayılan JSON seçeneklerini yapılandırır.
- Aşağıdaki JSON'yi döndürür
Deftere nakil sırasında{ "id": 1, "name": "Joe Smith" }
{ "Id": 1, "Name": "Joe Smith" }
İstek gövdesini okuma
bir veya HttpRequest parametresini kullanarak HttpContext istek gövdesini doğrudan okuyun:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/uploadstream", async (IConfiguration config, HttpRequest request) =>
{
var filePath = Path.Combine(config["StoredFilesPath"], Path.GetRandomFileName());
await using var writeStream = File.Create(filePath);
await request.BodyReader.CopyToAsync(writeStream);
});
app.Run();
Yukarıdaki kod:
- kullanarak HttpRequest.BodyReaderistek gövdesine erişir.
- İstek gövdesini yerel bir dosyaya kopyalar.
Yanıtlar
Yol işleyicileri aşağıdaki dönüş değer türlerini destekler:
IResult
based - Buna ve dahildirTask<IResult>
ValueTask<IResult>
string
- Buna ve dahildirTask<string>
ValueTask<string>
T
(Başka herhangi bir tür) - Buna ve dahildirTask<T>
ValueTask<T>
Örnek dönüş değerleri
dize dönüş değerleri
app.MapGet("/hello", () => "Hello World");
JSON dönüş değerleri
app.MapGet("/hello", () => new { Message = "Hello World" });
IResult dönüş değerleri
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Aşağıdaki örnek, yanıtı özelleştirmek için yerleşik sonuç türlerini kullanır:
app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound())
.Produces<Todo>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
JSON
app.MapGet("/hello", () => Results.Json(new { Message = "Hello World" }));
Özel Durum Kodu
app.MapGet("/405", () => Results.StatusCode(405));
Metin
app.MapGet("/text", () => Results.Text("This is some text"));
Akış
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var proxyClient = new HttpClient();
app.MapGet("/pokemon", async () =>
{
var stream = await proxyClient.GetStreamAsync("http://contoso/pokedex.json");
// Proxy the response as JSON
return Results.Stream(stream, "application/json");
});
app.Run();
Yönlendir
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
Dosya
app.MapGet("/download", () => Results.File("myfile.text"));
Yerleşik sonuçlar
Ortak sonuç yardımcıları statik sınıfta bulunur Microsoft.AspNetCore.Http.Results
.
Açıklama | Yanıt türü | Durum Kodu | API |
---|---|---|---|
Gelişmiş seçeneklerle JSON yanıtı yazma | application/json | 200 | Results.Json |
JSON yanıtı yazma | application/json | 200 | Sonuçlar.Tamam |
Metin yanıtı yazma | metin/düz (varsayılan), yapılandırılabilir | 200 | Results.Text |
Yanıtı bayt olarak yazma | application/octet-stream (varsayılan), yapılandırılabilir | 200 | Results.Bytes |
Yanıta bayt akışı yazma | application/octet-stream (varsayılan), yapılandırılabilir | 200 | Results.Stream |
İçerik ayrıştırma üst bilgisi ile bir dosyayı indirilmek üzere yanıta akışla aktarma | application/octet-stream (varsayılan), yapılandırılabilir | 200 | Results.File |
durum kodunu isteğe bağlı bir JSON yanıtıyla 404 olarak ayarlayın | Yok | 404 | Results.NotFound |
Durum kodunu 204 olarak ayarlayın | Yok | 204 | Results.NoContent |
durum kodunu isteğe bağlı bir JSON yanıtıyla 422 olarak ayarlayın | Yok | 422 | Results.UnprocessableEntity |
İsteğe bağlı JSON yanıtıyla durum kodunu 400 olarak ayarlayın | Yok | 400 | Results.BadRequest |
durum kodunu isteğe bağlı bir JSON yanıtıyla 409 olarak ayarlayın | Yok | 409 | Sonuçlar.Çakışma |
Yanıta sorun ayrıntıları JSON nesnesi yazma | Yok | 500 (varsayılan), yapılandırılabilir | Results.Problem |
Doğrulama hatalarıyla yanıta bir sorun ayrıntıları JSON nesnesi yazma | Yok | Yok, yapılandırılabilir | Results.ValidationProblem |
Sonuçları özelleştirme
Uygulamalar özel IResult bir tür uygulayarak yanıtları denetleyebilir. Aşağıdaki kod, BIR HTML sonuç türü örneğidir:
using System.Net.Mime;
using System.Text;
static class ResultsExtensions
{
public static IResult Html(this IResultExtensions resultExtensions, string html)
{
ArgumentNullException.ThrowIfNull(resultExtensions);
return new HtmlResult(html);
}
}
class HtmlResult : IResult
{
private readonly string _html;
public HtmlResult(string html)
{
_html = html;
}
public Task ExecuteAsync(HttpContext httpContext)
{
httpContext.Response.ContentType = MediaTypeNames.Text.Html;
httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(_html);
return httpContext.Response.WriteAsync(_html);
}
}
Bu özel sonuçları daha bulunabilir hale getirmek için öğesine Microsoft.AspNetCore.Http.IResultExtensions bir uzantı yöntemi eklemenizi öneririz.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/html", () => Results.Extensions.Html(@$"<!doctype html>
<html>
<head><title>miniHTML</title></head>
<body>
<h1>Hello World</h1>
<p>The time on the server is {DateTime.Now:O}</p>
</body>
</html>"));
app.Run();
Yetkilendirme
Yollar yetkilendirme ilkeleri kullanılarak korunabilir. Bunlar özniteliği aracılığıyla [Authorize]
veya yöntemi kullanılarak RequireAuthorization bildirilebilir:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebRPauth.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization(o => o.AddPolicy("AdminsOnly",
b => b.RequireClaim("admin", "true")));
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
var app = builder.Build();
app.UseAuthorization();
app.MapGet("/auth", [Authorize] () => "This endpoint requires authorization.");
app.MapGet("/", () => "This endpoint doesn't require authorization.");
app.MapGet("/Identity/Account/Login", () => "Sign in page at this endpoint.");
app.Run();
Yukarıdaki kod ile RequireAuthorizationyazılabilir:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Aşağıdaki örnekte ilke tabanlı yetkilendirme kullanılmaktadır:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebRPauth.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization(o => o.AddPolicy("AdminsOnly",
b => b.RequireClaim("admin", "true")));
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
var app = builder.Build();
app.UseAuthorization();
app.MapGet("/admin", [Authorize("AdminsOnly")] () =>
"The /admin endpoint is for admins only.");
app.MapGet("/admin2", () => "The /admin2 endpoint is for admins only.")
.RequireAuthorization("AdminsOnly");
app.MapGet("/", () => "This endpoint doesn't require authorization.");
app.MapGet("/Identity/Account/Login", () => "Sign in page at this endpoint.");
app.Run();
Kimliği doğrulanmamış kullanıcıların bir uç noktaya erişmesine izin verme
kimliği [AllowAnonymous]
doğrulanmamış kullanıcıların uç noktalara erişmesine izin verir:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Yollar CORS ilkeleri kullanılarak CORS etkinleştirilebilir. CORS, özniteliği veya [EnableCors]
yöntemi kullanılarak RequireCors bildirilebilir. Aşağıdaki örnekler CORS'yi etkinleştirir:
const string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
var app = builder.Build();
app.UseCors();
app.MapGet("/",() => "Hello CORS!");
app.Run();
using Microsoft.AspNetCore.Cors;
const string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
var app = builder.Build();
app.UseCors();
app.MapGet("/cors", [EnableCors(MyAllowSpecificOrigins)] () =>
"This endpoint allows cross origin requests!");
app.MapGet("/cors2", () => "This endpoint allows cross origin requests!")
.RequireCors(MyAllowSpecificOrigins);
app.Run();
Daha fazla bilgi için bkz . ASP.NET Core'da Çıkış Noktaları Arası İstekleri (CORS) Etkinleştirme
Ayrıca bkz.
ASP.NET Core