Aracılığıyla paylaş


En az API hızlı başvurusu

Not

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.

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.

Önemli

Bu bilgiler, ticari olarak piyasaya sürülmeden önce önemli ölçüde değiştirilebilen bir yayın öncesi ürünle ilgilidir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.

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ğunda HostingEnvironment "Development"ilk olarak eklenir.
  • UseRouting , kullanıcı kodu henüz çağrılmazsa UseRouting ve örneğin app.MapGetyapı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.
  • UseAuthenticationkullanıcı kodu henüz çağrılmazsa UseAuthentication ve hizmet sağlayıcısında algılanabilirse IAuthenticationSchemeProvider hemen sonra UseRouting eklenir. IAuthenticationSchemeProvider kullanılırken AddAuthenticationvarsayılan olarak eklenir ve kullanılarak hizmetler algılanır IServiceProviderIsService.
  • UseAuthorization , kullanıcı kodu henüz çağrılmazsa UseAuthorization ve hizmet sağlayıcısında algılanabilirse IAuthorizationHandlerProvider eklenir. IAuthorizationHandlerProvider kullanılırken AddAuthorizationvarsayılan olarak eklenir ve kullanılarak hizmetler algılanır IServiceProviderIsService.
  • Kullanıcı tarafından yapılandırılmış ara yazılım ve uç noktalar ile UseEndpointsarasına UseRouting 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 UseEndpointseklenmelidir.
  • 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 newile 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.jsonbelirtilen 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 3000yanıt verir.

Birden çok bağlantı noktası

Aşağıdaki kodda uygulama ve 4000bağ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 7777yanı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_PORTSkullanabilirASPNETCORE_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 ve appSettings.{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 messageatanı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 WebHostOptionsveya 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 WebApplicationyapı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 Deletegibi GetPostPut 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.csbulunması 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.

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/7dö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

, , HEADOPTIONSve DELETE HTTP yöntemleri GETgö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 Streamile 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ı nesnedir HttpRequest.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:

  • Koleksiyonlar, örneğin Liste ve Sözlük
  • Karmaşık türler, örneğin veya TodoProject

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 falseile ek bir isCompleted gizli giriş gösterir. isCompleted Form gönderildiğinde onay kutusu işaretlenirse, hem değerler true false hem de değer olarak gönderilir. Onay kutusunun işareti kaldırılırsa, yalnızca gizli giriş değeri false gönderilir. ASP.NET Core model bağlama işlemi, bir bool değere bağlanırken yalnızca ilk değeri okur ve bu da işaretli onay kutularına ve false işaretsiz onay kutularına neden true 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:

  1. 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.
  2. 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.1ile 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=99ile 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ı:

  1. Parametrede (From* öznitelikleri) aşağıdaki sırayla tanımlanan açık öznitelik:
    1. Yol değerleri: [FromRoute]
    2. Sorgu dizesi: [FromQuery]
    3. Üstbilgi: [FromHeader]
    4. Beden: [FromBody]
    5. Form: [FromForm]
    6. Hizmet: [FromServices]
    7. Parametre değerleri: [AsParameters]
  2. Özel türler
    1. HttpContext
    2. HttpRequest (HttpContext.Request)
    3. HttpResponse (HttpContext.Response)
    4. ClaimsPrincipal (HttpContext.User)
    5. CancellationToken (HttpContext.RequestAborted)
    6. IFormCollection (HttpContext.Request.Form)
    7. IFormFileCollection (HttpContext.Request.Form.Files)
    8. IFormFile (HttpContext.Request.Form.Files[paramName])
    9. Stream (HttpContext.Request.Body)
    10. PipeReader (HttpContext.Request.BodyReader)
  3. Parametre türü geçerli bir statik BindAsync yönteme sahiptir.
  4. Parametre türü bir dizedir veya geçerli bir statik TryParse yöntemi vardır.
    1. Parametre adı örneğin, yol şablonunda varsa, app.Map("/todo/{id}", (int id) => {});rotadan bağlanır.
    2. Sorgu dizesinden bağlanır.
  5. Parametre türü bağımlılık ekleme tarafından sağlanan bir hizmetse, kaynak olarak bu hizmeti kullanır.
  6. 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:

Yanıtlar

Yol işleyicileri aşağıdaki dönüş değer türlerini destekler:

  1. IResultbased - Buna ve dahildir Task<IResult>ValueTask<IResult>
  2. string- Buna ve dahildir Task<string>ValueTask<string>
  3. T(Başka herhangi bir tür) - Buna ve dahildir Task<T>ValueTask<T>
Dönüş değeri Davranış İçerik Türü
IResult Çerçeve IResult.ExecuteAsync'i çağırır Uygulama tarafından karar verildi IResult
string Çerçeve, dizeyi doğrudan yanıta yazar text/plain
T (Başka bir tür) Çerçeve JSON yanıtı serileştirir application/json

İş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 Resultsiç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 Developmentdevre 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.

Bu belge:

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ğunda HostingEnvironment "Development"ilk olarak eklenir.
  • UseRouting , kullanıcı kodu henüz çağrılmazsa UseRouting ve örneğin app.MapGetyapı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.
  • UseAuthenticationkullanıcı kodu henüz çağrılmazsa UseAuthentication ve hizmet sağlayıcısında algılanabilirse IAuthenticationSchemeProvider hemen sonra UseRouting eklenir. IAuthenticationSchemeProvider kullanılırken AddAuthenticationvarsayılan olarak eklenir ve kullanılarak hizmetler algılanır IServiceProviderIsService.
  • UseAuthorization , kullanıcı kodu henüz çağrılmazsa UseAuthorization ve hizmet sağlayıcısında algılanabilirse IAuthorizationHandlerProvider eklenir. IAuthorizationHandlerProvider kullanılırken AddAuthorizationvarsayılan olarak eklenir ve kullanılarak hizmetler algılanır IServiceProviderIsService.
  • Kullanıcı tarafından yapılandırılmış ara yazılım ve uç noktalar ile UseEndpointsarasına UseRouting 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 UseEndpointseklenmelidir.
  • 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 newile 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.jsonbelirtilen 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 3000yanıt verir.

Birden çok bağlantı noktası

Aşağıdaki kodda uygulama ve 4000bağ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 7777yanı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 ve appSettings.{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 messageatanı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 WebHostOptionsveya 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 WebApplicationyapı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 Deletegibi GetPostPut 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.csbulunması 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.

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/7dö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

, , HEADOPTIONSve DELETE HTTP yöntemleri GETgö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 Streamile 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ı nesnedir HttpRequest.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:

  1. 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.
  2. 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.1ile 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=99ile 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ı:

  1. Parametrede (From* öznitelikleri) aşağıdaki sırayla tanımlanan açık öznitelik:
    1. Yol değerleri: [FromRoute]
    2. Sorgu dizesi: [FromQuery]
    3. Üstbilgi: [FromHeader]
    4. Beden: [FromBody]
    5. Hizmet: [FromServices]
    6. Parametre değerleri: [AsParameters]
  2. Özel türler
    1. HttpContext
    2. HttpRequest (HttpContext.Request)
    3. HttpResponse (HttpContext.Response)
    4. ClaimsPrincipal (HttpContext.User)
    5. CancellationToken (HttpContext.RequestAborted)
    6. IFormFileCollection (HttpContext.Request.Form.Files)
    7. IFormFile (HttpContext.Request.Form.Files[paramName])
    8. Stream (HttpContext.Request.Body)
    9. PipeReader (HttpContext.Request.BodyReader)
  3. Parametre türü geçerli bir statik BindAsync yönteme sahiptir.
  4. Parametre türü bir dizedir veya geçerli bir statik TryParse yöntemi vardır.
    1. Rota şablonunda parametre adı varsa. id içindeapp.Map("/todo/{id}", (int id) => {});, yolundan bağlıdır.
    2. Sorgu dizesinden bağlanır.
  5. Parametre türü bağımlılık ekleme tarafından sağlanan bir hizmetse, kaynak olarak bu hizmeti kullanır.
  6. 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:

Yanıtlar

Yol işleyicileri aşağıdaki dönüş değer türlerini destekler:

  1. IResultbased - Buna ve dahildir Task<IResult>ValueTask<IResult>
  2. string- Buna ve dahildir Task<string>ValueTask<string>
  3. T(Başka herhangi bir tür) - Buna ve dahildir Task<T>ValueTask<T>
Dönüş değeri Davranış İçerik Türü
IResult Çerçeve IResult.ExecuteAsync'i çağırır Uygulama tarafından karar verildi IResult
string Çerçeve, dizeyi doğrudan yanıta yazar text/plain
T (Başka bir tür) Çerçeve JSON yanıtı serileştirir application/json

İş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 Resultsiç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 ş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.

Bağlantı noktalarıyla çalışma

Visual Studio veya dotnet newile 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 3000yanıt verir.

Birden çok bağlantı noktası

Aşağıdaki kodda uygulama ve 4000bağ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 7777yanı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 ve appSettings.{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 messageatanı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 WebHostOptionsveya 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 WebApplicationyapı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";
    }
}

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/7dö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

, , HEADOPTIONSve DELETE HTTP yöntemleri GETgö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:

  1. 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.
  2. 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.1ile 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=99ile 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ı:

  1. Parametrede (From* öznitelikleri) aşağıdaki sırayla tanımlanan açık öznitelik:
    1. Yol değerleri: [FromRoute]
    2. Sorgu dizesi: [FromQuery]
    3. Üstbilgi: [FromHeader]
    4. Beden: [FromBody]
    5. Hizmet: [FromServices]
  2. Özel türler
    1. HttpContext
    2. HttpRequest (HttpContext.Request)
    3. HttpResponse (HttpContext.Response)
    4. ClaimsPrincipal (HttpContext.User)
    5. CancellationToken (HttpContext.RequestAborted)
  3. Parametre türünün geçerli BindAsync bir yöntemi vardır.
  4. Parametre türü bir dizedir veya geçerli TryParse bir yöntemi vardır.
    1. Rota şablonunda parametre adı varsa. id içindeapp.Map("/todo/{id}", (int id) => {});, yolundan bağlıdır.
    2. Sorgu dizesinden bağlanır.
  5. Parametre türü bağımlılık ekleme tarafından sağlanan bir hizmetse, kaynak olarak bu hizmeti kullanır.
  6. 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
    {
      "id": 1,
      "name": "Joe Smith"
    }
    
    Deftere nakil sırasında
    {
      "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:

Yanıtlar

Yol işleyicileri aşağıdaki dönüş değer türlerini destekler:

  1. IResultbased - Buna ve dahildir Task<IResult>ValueTask<IResult>
  2. string- Buna ve dahildir Task<string>ValueTask<string>
  3. T(Başka herhangi bir tür) - Buna ve dahildir Task<T>ValueTask<T>
Dönüş değeri Davranış İçerik Türü
IResult Çerçeve IResult.ExecuteAsync'i çağırır Uygulama tarafından karar verildi IResult
string Çerçeve, dizeyi doğrudan yanıta yazar text/plain
T (Başka bir tür) Çerçeve, JSON yanıtı seri hale getirecektir application/json

Ö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.

Minimum API'lerde OpenAPI desteği