Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Note
Ez nem a cikk legújabb verziója. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.
Warning
A ASP.NET Core ezen verziója már nem támogatott. További információ: .NET és .NET Core támogatási szabályzat. Az aktuális verzióért nézze meg ennek a cikknek a .NET 9-es verzióját.
Ez a dokumentum:
- Rövid útmutató a minimális API-khoz.
- Tapasztalt fejlesztőknek készült. Bevezetésként tekintse meg oktatóanyagot: Minimális API létrehozása ASP.NET Core.
A minimális API-k a következőkből állnak:
WebApplication
A következő kódot egy ASP.NET Core-sablon hozza létre:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző kód a parancssori dotnet new web vagy a Visual Studio Üres websablonjának kiválasztásával hozható létre.
A következő kód létrehoz egy WebApplication (app) anélkül, hogy explicit módon létrehoz egy WebApplicationBuilder:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create inicializálja a WebApplication osztály új példányát előre konfigurált alapértelmezett értékekkel.
WebApplication bizonyos feltételektől függően automatikusan hozzáadja a következő köztes szoftvereket a Minimal API-alkalmazásokhoz :
- Először hozzáadódik a
UseDeveloperExceptionPage, amikor aHostingEnvironment"Development". -
UseRoutingmásodikként kerül hozzáadásra, ha a felhasználói kód még nem hívta meg aUseRouting-et, és ha vannak konfigurált végpontok, példáulapp.MapGet. -
UseEndpointsa köztesréteg-folyamatok végéhez kerül hozzáadásra, ha bármelyik végpont konfigurálva van. -
UseAuthenticationazonnal hozzáadódikUseRoutingután, ha a felhasználói kód még nem hívta megUseAuthentication-t, és ha aIAuthenticationSchemeProviderészlelhető a szolgáltatónál.IAuthenticationSchemeProvideralapértelmezés szerintAddAuthenticationhasználatakor lesz hozzáadva, a szolgáltatások pedigIServiceProviderIsServicehasználatával észlelhetők. -
UseAuthorizationakkor lesz a következő, ha a felhasználói kód még nem hívta felUseAuthorization, ésIAuthorizationHandlerProviderészlelhető-e a szolgáltatóban.IAuthorizationHandlerProvideralapértelmezés szerintAddAuthorizationhasználatakor lesz hozzáadva, a szolgáltatások pedigIServiceProviderIsServicehasználatával észlelhetők. - A felhasználó által konfigurált köztes szoftver és végpontok
UseRoutingésUseEndpointsközé kerülnek.
Az alkalmazáshoz hozzáadott automatikus köztes szoftver gyakorlatilag a következő kódot eredményezi:
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 => {});
Bizonyos esetekben az alapértelmezett köztes szoftverkonfiguráció nem megfelelő az alkalmazáshoz, és módosítást igényel. Például a UseCors-t UseAuthentication és UseAuthorizationelőtt kell meghívni. Az alkalmazásnak meg kell hívnia UseAuthentication és UseAuthorization, ha UseCors van meghívva:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Ha a köztes szoftvereket az útvonalegyeztetés előtt kell futtatni, UseRouting kell meghívni, és a köztes szoftvernek a UseRoutinghívása előtt kell lennie. ebben az esetben nem szükséges UseEndpoints, mivel a korábban ismertetett módon automatikusan hozzáadja:
app.Use((context, next) =>
{
return next(context);
});
app.UseRouting();
// other middleware and endpoints
Terminál köztes szoftver hozzáadásakor:
- A köztes szoftvert
UseEndpointsután kell hozzáadni. - Az alkalmazásnak meg kell hívnia
UseRoutingésUseEndpoints, hogy a terminál közbenső szoftvere a megfelelő helyre kerüljön.
app.UseRouting();
app.MapGet("/", () => "hello world");
app.UseEndpoints(e => {});
app.Run(context =>
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
A terminál köztes szoftver olyan köztes szoftver, amely akkor fut, ha egyetlen végpont sem kezeli a kérést.
Portok használata
Amikor webalkalmazást hoz létre a Visual Studióval vagy dotnet new, létrejön egy Properties/launchSettings.json fájl, amely meghatározza azokat a portokat, amelyekre az alkalmazás válaszol. Az alábbi portbeállítási mintákban az alkalmazás Visual Studióból való futtatása hibaüzenetet ad vissza Unable to connect to web server 'AppName'. A Visual Studio hibát ad vissza, mert a Properties/launchSettings.jsonmegadott portot várja, de az alkalmazás a app.Run("http://localhost:3000")által megadott portot használja. Futtassa a következő portmódosítási mintákat a parancssorból.
Az alábbi szakaszok azt a portot állítják be, amelyekre az alkalmazás válaszol.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
Az előző kódban az alkalmazás reagál a 3000porton.
Több port
Az alábbi kódban az alkalmazás válaszol a port 3000 és 4000.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
A port beállítása a parancssorból
Az alábbi parancs lehetővé teszi, hogy az alkalmazás a 7777porton fogadjon.
dotnet run --urls="https://localhost:7777"
Ha a Kestrel végpont is konfigurálva van a appsettings.json fájlban, a appsettings.json megadott URL-címet használja a rendszer. További információért lásd: Kestrel végpont konfiguráció
A port beolvasása a környezetből
A következő kód beolvassa a portot a környezetből:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
A port környezetből való beállításának elsődleges módja a ASPNETCORE_URLS környezeti változó használata, amely az alábbi szakaszban látható.
Portok beállítása a ASPNETCORE_URLS környezeti változón keresztül
A port beállításához elérhető a ASPNETCORE_URLS környezeti változó:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS több URL-címet is támogat:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
Figyelés az összes felületen
Az alábbi minták azt mutatják be, hogy az összes felületen figyelnek
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();
Hallgatás minden felületen az ASPNETCORE_URLS használatával
Az előző minták használhatják a ASPNETCORE_URLS-t.
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
Figyeljen minden interfészen az ASPNETCORE_HTTPS_PORTS használatával
Az előző minták használhatják a ASPNETCORE_HTTPS_PORTS és ASPNETCORE_HTTP_PORTSkódokat.
ASPNETCORE_HTTP_PORTS=3000;5005
ASPNETCORE_HTTPS_PORTS=5000
További információ: Végpontok konfigurálása a ASP.NET Core Kestrel webkiszolgálóhoz
HTTPS beállítása fejlesztési tanúsítvánnyal
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
A fejlesztési tanúsítvánnyal kapcsolatos további információkért lásd: Az ASP.NET Core HTTPS fejlesztési tanúsítvány hitelesítése Windows és macOS.
HTTPS megadása egyéni tanúsítvány használatával
Az alábbi szakaszok bemutatják, hogyan adhatja meg az egyéni tanúsítványt a appsettings.json fájllal és konfigurációval.
Adja meg a testreszabott tanúsítványt a appsettings.json jelöléssel
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Az egyéni tanúsítvány megadása konfigurációval
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();
A tanúsítvány API-k használata
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();
A környezet olvasása
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();
További információ a környezet használatáról: ASP.NET Core futtatókörnyezetek
Configuration
A következő kód a konfigurációs rendszerből olvas be:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Config failed!";
app.MapGet("/", () => message);
app.Run();
További információ: ASP.NET Core konfiguráció
Logging
Az alábbi kód egy üzenetet ír az alkalmazás indítási naplójába:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
További információ: Naplózás a .NET-ben és a ASP.NET Core-ban
A függőség-injektálás (DI) konténer elérése
Az alábbi kód bemutatja, hogyan kérhet le szolgáltatásokat a DI-tárolóból az alkalmazás indításakor:
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();
Az alábbi kód bemutatja, hogyan érheti el a kulcsokat a DI-tárolóból a [FromKeyedServices] attribútum használatával:
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.";
}
További információ a DI-ről a Függőséginjektálás az ASP.NET Corecímű részben található.
WebApplicationBuilder
Ez a szakasz WebApplicationBuilderhasználatával tartalmaz mintakódot.
A tartalomgyöker, az alkalmazásnév és a környezet módosítása
A következő kód állítja be a tartalom gyökerét, az alkalmazás nevét és a környezetet:
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 inicializálja a WebApplicationBuilder osztály új példányát előre konfigurált alapértelmezett beállításokkal.
További információ: ASP.NET Alapvető alapismeretek áttekintése
A tartalomgyöker, az alkalmazás neve és a környezet módosítása környezeti változók vagy parancssor használatával
Az alábbi táblázat a tartalomgyöker, az alkalmazásnév és a környezet módosításához használt környezeti változót és parancssori argumentumot mutatja be:
| funkció | Környezet változó | Parancssori argumentum |
|---|---|---|
| Alkalmazás neve | ASPNETCORE_APPLICATIONNAME | --applicationName |
| Környezet neve | ASPNETCORE_ENVIRONMENT | --environment |
| Tartalomgyökér | ASPNETCORE_CONTENTROOT | --contentRoot |
Konfigurációszolgáltatók hozzáadása
Az alábbi minta hozzáadja az INI-konfigurációszolgáltatót:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Részletes információért lásd: Fájlkonfigurációs szolgáltatók az ASP.NET Core konfigurációjában.
Olvasási konfiguráció
Alapértelmezés szerint a WebApplicationBuilder több forrásból olvassa be a konfigurációt, beleértve a következőket:
-
appSettings.jsonésappSettings.{environment}.json - Környezeti változók
- A parancssor
A konfigurációs források teljes listáját a Alapértelmezett konfiguráció című részben találja, amely része a konfigurációnak az ASP.NET Coredokumentumban.
Az alábbi kód beolvassa HelloKey konfigurációból, és megjeleníti az értéket a / végponton. Ha a konfiguráció értéke null, a "Hello" messagevan hozzárendelve:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
A környezet olvasása
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsDevelopment())
{
Console.WriteLine($"Running in development.");
}
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Naplózási szolgáltatók hozzáadása
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();
Szolgáltatások hozzáadása
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();
Az IHostBuilder testreszabása
A IHostBuilder meglévő bővítési metódusok a Gazdagép tulajdonsághasználatával érhetők el.
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();
Az IWebHostBuilder testreszabása
A IWebHostBuilder bővítménymetelyek a WebApplicationBuilder.WebHost tulajdonság használatával érhetők el.
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();
Webes gyökér módosítása
Alapértelmezés szerint a webes gyökér a wwwroot mappában lévő tartalomgyökerhez képest van. A webes gyökér az, ahol a Statikus fájl köztes szoftver statikus fájlokat keres. A webes gyökér a WebHostOptions, a parancssor vagy a UseWebRoot metódus használatával módosítható:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Egyéni függőséginjektáló (DI) tároló
Az alábbi példa Autofachasznál:
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();
Köztes szoftver hozzáadása
Bármely meglévő ASP.NET Core middleware konfigurálható a WebApplication:
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
További információ: ASP.NET Core Middleware
Fejlesztői kivételoldal
WebApplication.CreateBuilder inicializálja a WebApplicationBuilder osztály új példányát előre konfigurált alapértelmezett értékekkel. A fejlesztői kivételoldal engedélyezve van az előre konfigurált alapértelmezett beállításokban. Ha a következő kódot a fejlesztési környezetben futtatja, a / navigálással egy barátságos oldal jelenik meg, ami megmutatja a kivételt.
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 Middleware
Az alábbi táblázat felsorolja a minimális API-kban gyakran használt köztes szoftvereket.
| Middleware | Description | API |
|---|---|---|
| Authentication | Hitelesítési támogatást nyújt. | UseAuthentication |
| Authorization | Engedélyezési támogatást nyújt. | UseAuthorization |
| CORS | A forrásközi erőforrásmegosztást konfigurálja. | UseCors |
| Kivételkezelő | Globálisan kezeli a köztes szoftverfolyamat által kidobott kivételeket. | UseExceptionHandler |
| Továbbított fejlécek | Továbbítja a proxizott fejléceket az aktuális kérelemre. | UseForwardedHeaders |
| HTTPS-átirányítás | Átirányítja az összes HTTP-kérést a HTTPS-be. | UseHttpsRedirection |
| HTTP szigorú átviteli biztonsági (HSTS) | Biztonsági funkciókat javító middleware, amely egy speciális válaszfejlécet ad hozzá. | UseHsts |
| Kérelemnaplózás | TÁMOGATJA a HTTP-kérések és válaszok naplózását. | UseHttpLogging |
| Kérelem időtúllépései | Támogatja a kérések időtúllépéseinek konfigurálását, a globális alapértelmezett és végpontonkénti beállításokat. | UseRequestTimeouts |
| W3C-kérésnaplózás | Támogatja a HTTP-kérések és válaszok naplózását W3C formátumban. | UseW3CLogging |
| Válasz gyorsítótárazása | Támogatást nyújt a gyorsítótárazási válaszokhoz. | UseResponseCaching |
| Választömörítés | Támogatja a válaszok tömörítését. | UseResponseCompression |
| Session | Támogatást nyújt a felhasználói munkamenetek kezeléséhez. | UseSession |
| Statikus fájlok | Támogatja a statikus fájlok és a címtárböngészés kiszolgálását. | UseStaticFiles, UseFileServer |
| WebSockets | Engedélyezi a WebSockets protokollt. | UseWebSockets |
A következő szakaszok a kérések kezelését ismertetik: útválasztás, paraméterkötés és válaszok.
Routing
A konfigurált WebApplication támogatja Map{Verb} , és MapMethods hol {Verb} van egy teve-eset http metódus, például Get: , Post, Putvagy Delete:
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();
A metódusoknak átadott Delegate argumentumokat "útvonalkezelőknek" nevezzük.
Útvonalkezelők
Az útvonalkezelők olyan metódusok, amelyek az útvonal egyezésekor futnak. Az útvonalkezelők lehetnek lambdakifejezések, helyi függvények, példánymetódusok vagy statikus metódusok. Az útvonalkezelők lehetnek szinkronok vagy aszinkronok.
Lambda kifejezés
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();
Helyi függvény
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Példánymetódus
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";
}
}
Statikus metódus
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";
}
}
A Program.cs kívül definiált végpont
A minimális API-knak nem kell a(z) Program.cs-ban lennie.
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" });
});
}
}
Lásd még a később ebben a cikkben található Útvonalcsoportok részt.
Elnevezett végpontok és hivatkozás létrehozása
A végpontok nevet adhatnak a végpont URL-címeinek létrehozásához. A névvel ellátott végpontok használatával elkerülhető, hogy az alkalmazásokban ne kelljen kemény kódútvonalakat használni:
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();
Az előző kód megjeleníti a The link to the hello route is /hello-t a / végpontról.
MEGJEGYZÉS: A végpontok neve megkülönbözteti a kis- és nagybetűket.
Végpontnevek:
- Globálisan egyedinek kell lennie.
- OpenAPI-műveletazonosítóként használatos, ha az OpenAPI-támogatás engedélyezve van. További információ: OpenAPI.
Útvonalparaméterek
Az útvonalparaméterek az útvonalminta definíciójának részeként rögzíthetők:
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();
Az előző kód a The user id is 3 and book id is 7 értéket adja vissza az URI /users/3/books/7-ből.
Az útvonalkezelő deklarálhatja a rögzítendő paramétereket. Amikor egy olyan útvonalra irányuló kérést küld, amelynek a paraméterei rögzítésre vannak deklarálva, a rendszer elemzi és továbbítja a paramétereket a kezelőnek. Ez megkönnyíti az értékek biztonságos típusba rögzítését. Az előző kódban userId és bookId is int.
Az előző kódban, ha bármelyik útvonalértéket nem lehet int-é konvertálni, kivétel keletkezik. A GET kérés /users/hello/books/3 a következő kivételt okozza:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Helyettesítő karakter és az összes útvonal elfogása
A következő átfogó útvonal a "/posts/hello" végpontról Routing to hello-t ad vissza:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Útvonalkorlátozások
Az útvonalkorlátozások korlátozzák az útvonalak egyező viselkedését.
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();
Az alábbi táblázat az előző útvonalsablonokat és azok viselkedését mutatja be:
| Útvonalsablon | Példa egyező URI-ra |
|---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
További információért lásd: Útválasztási korlátozások hivatkozása a Útválasztás ASP.NET Corerészében.
Útvonalcsoportok
A MapGroup bővítménymetódus segít a végpontcsoportok közös előtaggal való rendszerezésében. Csökkenti az ismétlődő kódot, és lehetővé teszi a végpontok teljes csoportjainak testreszabását egyetlen hívással olyan metódusokhoz, mint a RequireAuthorization és WithMetadata, amelyek végpont metaadatait adják hozzá.
A következő kód például két hasonló végpontcsoportot hoz létre:
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;
}
Ebben a forgatókönyvben a Location fejléc relatív címét használhatja a 201 Created eredményben:
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
A végpontok első csoportja csak a /public/todos előtagú kéréseknek felel meg, és hitelesítés nélkül is elérhetők. A végpontok második csoportja csak a /private/todos előtagú kéréseknek felel meg, és hitelesítést igényel.
A QueryPrivateTodosvégpontszűrő-előállító egy helyi függvény, amely módosítja az útvonalkezelő TodoDb paramétereit annak érdekében, hogy lehetővé tegye a privát teendőadatok elérését és tárolását.
Az útvonalcsoportok a beágyazott csoportokat és az összetett előtagmintákat is támogatják útvonalparaméterekkel és korlátozásokkal. Az alábbi példában a user csoporthoz hozzárendelt útvonalkezelő rögzítheti a külső csoport előtagjaiban definiált {org} és {group} útvonalparamétereket.
Az előtag üres is lehet. Ez akkor lehet hasznos, ha végponti metaadatokat vagy szűrőket ad hozzá a végpontok egy csoportjához az útvonalminta módosítása nélkül.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
A szűrők vagy metaadatok csoporthoz való hozzáadása ugyanúgy viselkedik, mint az egyes végpontokhoz való egyenkénti hozzáadásuk, mielőtt további szűrőket vagy metaadatokat ad hozzá egy belső csoporthoz vagy adott végponthoz.
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);
});
A fenti példában a külső szűrő naplózza a bejövő kérést a belső szűrő előtt annak ellenére, hogy másodikként lett hozzáadva. Mivel a szűrők különböző csoportokra lettek alkalmazva, a egymáshoz viszonyított sorrend nem számít. A rendelésszűrők hozzáadásának sorrendje számít, ha ugyanarra a csoportra vagy egy adott végpontra alkalmazzák.
A /outer/inner/ kérés a következőket naplózza:
/outer group filter
/inner group filter
MapGet filter
Paraméterkötés
A paraméterkötés a kérelemadatok erősen gépelt paraméterekké alakításának folyamata, amelyeket az útvonalkezelők fejeznek ki. A kötési forrás határozza meg, hogy a paraméterek honnan vannak kötve. A kötési források lehetnek explicitek vagy következtethetők a HTTP-módszer és a paramétertípus alapján.
Támogatott kötési források:
- Útvonalértékek
- Lekérdezési karakterlánc
- Header
- Törzs (mint JSON)
- Űrlapértékek
- Függőséginjektálás által biztosított szolgáltatások
- Custom
A következő GET útvonalkezelő az alábbi paraméterkötési források némelyikét használja:
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 { }
Fő paraméterkötési funkciók
-
Explicit kötés: Használjon olyan attribútumokat, mint a
[FromRoute],[FromQuery],[FromHeader],[FromBody], ,[FromForm]és[FromServices]explicit módon adja meg a kötési forrásokat. -
Űrlapérték-kötés: Űrlapértékek kötése
[FromForm]attribútummal, beleértve a fájlfeltöltések támogatásátIFormFileésIFormFileCollection. - Összetett típusok: Gyűjteményekhez és összetett típusokhoz való kötés űrlapokból, lekérdezési sztringekből és fejlécekből.
- Egyéni kötés: Egyéni kötési logika implementálása a ,
TryParse, vagy aBindAsyncfelületen. - Választható paraméterek: Támogatja a null értékű típusokat és az opcionális paraméterek alapértelmezett értékeit.
- Függőséginjektálás: A paraméterek automatikusan kötődnek a DI-tárolóban regisztrált szolgáltatásokhoz.
-
Speciális típusok: Automatikus kötés a
HttpContext,HttpRequest,HttpResponse,CancellationToken,ClaimsPrincipalésStreamPipeReader.
Tudj meg többet: A paraméterkötéssel kapcsolatos részletes információkért, beleértve a speciális forgatókönyveket, az érvényesítést, a kötési elsőbbséget és a hibaelhárítást, tekintse meg a paraméterkötést a Minimal API-alkalmazásokban.
Json+PipeReader deszerializálás minimális API-kban
A .NET 10-től kezdve a ASP.NET Core alábbi funkcionális területei a Stream helyett a PipeReader-alapú túlterheléseket használják JsonSerializer.DeserializeAsync :
- Minimális API-k (paraméterkötés, olvasási kérelem törzse)
- MVC (bemeneti formázók, modell)
- A HttpRequestJsonExtensions kérelem törzsének JSON-ként való olvasására használható bővítménymetelyek.
A legtöbb alkalmazás esetében a Streamről a PipeReaderre való áttérés jobb teljesítményt biztosít anélkül, hogy módosításokat kellene végrehajtania az alkalmazáskódban. Ha azonban az alkalmazás egyéni konverterrel rendelkezik, előfordulhat, hogy a konverter nem megfelelően működik Utf8JsonReader.HasValueSequence . Ha nem, akkor az eredmény hibákhoz vezethet, például ArgumentOutOfRangeException, vagy hiányzó adatokhoz a deszerializáláskor. A konverter pipeReaderrel kapcsolatos hibák nélkül történő működéséhez az alábbi lehetőségek állnak rendelkezésre.
1. lehetőség: Ideiglenes kerülő megoldás
A gyors áthidaló megoldás az, hogy visszatér a Streamhez a PipeReader támogatása nélkül. A beállítás implementálásához állítsa a "Microsoft.AspNetCore.UseStreamBasedJsonParsing" AppContext kapcsolót "true" értékre. Javasoljuk, hogy ezt csak ideiglenes kerülő megoldásként végezze el, és frissítse a konvertert, hogy a lehető leghamarabb támogatást nyújtson HasValueSequence . Előfordulhat, hogy a kapcsoló el lesz távolítva a .NET 11-ben. Az egyetlen célja az volt, hogy időt adjon a fejlesztőknek a konverterek frissítésére.
2. lehetőség: Az implementációk JsonConverter gyors javítása
Ehhez a javításhoz egy tömböt foglal le a ReadOnlySequence. Ez a példa a kód megjelenését mutatja be:
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
// previous code
}
3. lehetőség: Bonyolultabb, de jobb teljesítményű javítás
Ez a javítás magában foglalja egy külön kódútvonal beállítását a ReadOnlySequence kezeléshez:
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.HasValueSequence)
{
reader.ValueSequence;
// ReadOnlySequence optimized path
}
else
{
reader.ValueSpan;
// ReadOnlySpan optimized path
}
}
További információkért lásd:
Érvényesítési támogatás minimális API-kban
Az érvényesítés engedélyezése lehetővé teszi, hogy a ASP.NET Core-futtatókörnyezet végrehajtsa a következőn definiált érvényesítéseket:
- Query
- Header
- A kérés tartalma
Az érvényesítések a névtér attribútumai DataAnnotations alapján vannak definiálva.
Ha egy minimális API-végpont paramétere osztály- vagy rekordtípus, a rendszer automatikusan érvényesítési attribútumokat alkalmaz. Például:
public record Product(
[Required] string Name,
[Range(1, 1000)] int Quantity);
A fejlesztők a következővel szabják testre az érvényesítési rendszer viselkedését:
- Egyéni
[Validation]attribútum-implementációk létrehozása. - Az összetett érvényesítési logika felületének
IValidatableObjectimplementálása.
Ha az ellenőrzés sikertelen, a futtatókörnyezet 400 – Hibás kérés választ ad vissza az érvényesítési hibák részleteivel.
A minimális API-k beépített érvényesítési támogatásának engedélyezése
A Minimal API-k beépített érvényesítési támogatásának engedélyezéséhez hívja meg a AddValidation bővítménymetódust, hogy regisztrálja a szükséges szolgáltatásokat az alkalmazás szolgáltatástárolójában:
builder.Services.AddValidation();
Az implementáció automatikusan felderíti a Minimal API-kezelőkben vagy a Minimal API-kezelőkben definiált alaptípusok típusait. Egy végpontszűrő érvényesítést végez ezeken a típusokon, és minden végponthoz hozzá lesz adva.
Az ellenőrzés letiltható adott végpontok esetében a DisableValidation bővítménymetódus használatával, ahogyan az alábbi példában is látható:
app.MapPost("/products",
([EvenNumber(ErrorMessage = "Product ID must be even")] int productId, [Required] string name)
=> TypedResults.Ok(productId))
.DisableValidation();
Érvényesítési hibaválaszok testreszabása az IProblemDetailsService használatával
Implementációval testre szabhatja a minimális API-érvényesítési logika hibaválaszait IProblemDetailsService . Regisztrálja ezt a szolgáltatást az alkalmazás szolgáltatásgyűjteményében a konzisztens és felhasználóspecifikus hibaválaszok engedélyezéséhez. A minimális API-ellenőrzés támogatása a .NET 10 ASP.NET Core-ban jelent meg.
Egyéni érvényesítési hibaválaszok implementálása:
- Az alapértelmezett implementáció implementálása IProblemDetailsService vagy használata
- A szolgáltatás regisztrálása a DI-tárolóban
- Az érvényesítési rendszer automatikusan a regisztrált szolgáltatást használja az érvényesítési hibaválaszok formázására
Az érvényesítési hibaválaszok az IProblemDetailsService szolgáltatással való testreszabásáról további információt a Válaszok létrehozása minimal API-alkalmazásokban című témakörben talál.
Responses
Az útvonalkezelők a következő típusú visszatérési értékeket támogatják:
-
IResultalapú – Ez magában foglalja aTask<IResult>-et és aValueTask<IResult>-t -
string– Ebbe beletartozikTask<string>ésValueTask<string> -
T(Bármilyen más típus) – Ebbe beletartozikTask<T>ésValueTask<T>
| Visszaadott érték | Behavior | Content-Type |
|---|---|---|
IResult |
A keretrendszer meghívja IResult.ExecuteAsync | A döntést a IResult végrehajtása hozta meg. |
string |
A keretrendszer közvetlenül a válaszba írja a sztringet | text/plain |
T (bármilyen más típus) |
A keretrendszer JSON-szerializálja a választ | application/json |
Az útvonalkezelő visszatérési értékeinek részletes útmutatója: Válaszok létrehozása minimális API-alkalmazásokban
Példa visszaadott értékekre
karakterlánc visszaadott értékei
app.MapGet("/hello", () => "Hello World");
JSON visszaadott értékek
app.MapGet("/hello", () => new { Message = "Hello World" });
TypedResults visszatérése
A következő kód egy TypedResultsad vissza:
app.MapGet("/hello", () => TypedResults.Ok(new Message() { Text = "Hello World!" }));
A TypedResults visszaadása előnyben részesíti a Resultsvisszatérését. További információ: TypedResults vs Results.
IResult visszatérési értékek
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Az alábbi példa a beépített eredménytípusokat használja a válasz testreszabásához:
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" }));
Egyéni állapotkód
app.MapGet("/405", () => Results.StatusCode(405));
Text
app.MapGet("/text", () => Results.Text("This is some text"));
Stream
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");
});
További példákért lásd Válaszok létrehozása minimal API-alkalmazásokban.
Redirect
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
File
app.MapGet("/download", () => Results.File("myfile.text"));
Beépített eredmények
A Results és TypedResults statikus osztályokban gyakori eredmény-segítők léteznek. A TypedResults visszaadása előnyben részesíti a Resultsvisszatérését. További információ: TypedResults vs Results.
Fejlécek módosítása
A válaszfejlécek módosításához használja a HttpResponse objektumot:
app.MapGet("/", (HttpContext context) => {
// Set a custom header
context.Response.Headers["X-Custom-Header"] = "CustomValue";
// Set a known header
context.Response.Headers.CacheControl = $"public,max-age=3600";
return "Hello World";
});
Eredmények testreszabása
Az alkalmazások egyéni IResult típus implementálásával szabályozhatják a válaszokat. Az alábbi kód egy PÉLDA EGY HTML-eredménytípusra:
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);
}
}
Javasoljuk, hogy adjon hozzá egy bővítménymetódust a Microsoft.AspNetCore.Http.IResultExtensions az egyéni eredmények felderíthetőbbé tétele érdekében.
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();
Beírt eredmények
Az IResult interfész olyan minimális API-kból visszaadott értékeket jelölhet, amelyek nem használják ki a JSON implicit támogatását a visszaadott objektum HTTP-válaszra való szerializálásához. A statikus Eredmények osztály különböző IResult típusú válaszok megjelenítésére szolgál. Például állítsa be a válaszállapot-kódot, vagy átirányítsa egy másik URL-címre.
A IResult implementáló típusok nyilvánosak, így teszteléskor lehetővé teszik a típusok helyességére vonatkozó állításokat. Például:
[TestClass()]
public class WeatherApiTests
{
[TestMethod()]
public void MapWeatherApiTest()
{
var result = WeatherApi.GetAllWeathers();
Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
}
}
A statikus TypedResults osztály megfelelő metódusainak visszatérési típusait megvizsgálva megtalálhatja azt a megfelelő nyilvános IResult típust, amelyre át lehet alakítani.
További példákért lásd Válaszok létrehozása minimal API-alkalmazásokban.
Filters
További információ: Szűrők a Minimális API-alkalmazásokban.
Authorization
Az útvonalak engedélyezési szabályzatokkal védhetők. Ezek deklarálhatók a [Authorize] attribútummal vagy a RequireAuthorization metódussal:
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();
Az előző kód így is írható RequireAuthorization:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Az alábbi minta a házirenden alapuló engedélyezés használatát mutatja be.
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();
Végpont elérésének engedélyezése hitelesítés nélküli felhasználók számára
A [AllowAnonymous] lehetővé teszi, hogy a hitelesítés nélküli felhasználók hozzáférjenek a végpontokhoz:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Az útvonalak CORS- engedélyezhetők CORS-szabályzatokkal. A CORS deklarálható a [EnableCors] attribútummal vagy a RequireCors metódussal. A következő minták engedélyezik a CORS-t:
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();
További információkért nézze meg: Kereszt-származási kérelmek engedélyezése (CORS) az ASP.NET Core
ValidateScopes és ValidateOnBuild
A ValidateScopes és a ValidateOnBuild alapértelmezés szerint engedélyezve vannak a Fejlesztési környezetben, de más környezetekben le vannak tiltva.
Ha ValidateOnBuildtrue, a DI-tároló ellenőrzi a szolgáltatás konfigurációját a létrehozáskor. Ha a szolgáltatáskonfiguráció érvénytelen, a build az alkalmazás indításakor meghiúsul, nem pedig futásidőben, amikor a szolgáltatást kérik.
Ha ValidateScopestrue, a DI-tároló ellenőrzi, hogy a hatókörrel rendelkező szolgáltatás nincs-e feloldva a gyökérhatókörből. A hatókörrel rendelkező szolgáltatás gyökérhatókörből való feloldása memóriavesztést okozhat, mivel a szolgáltatás a kérés hatókörénél hosszabb ideig marad a memóriában.
A ValidateScopes és a ValidateOnBuild alapértelmezés szerint hamisak a nem fejlesztési módban teljesítménybeli okokból.
Az alábbi kód azt mutatja, hogy a ValidateScopes alapértelmezés szerint engedélyezve van fejlesztési módban, de kiadási módban le van tiltva:
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 { }
Az alábbi kód azt mutatja, hogy a ValidateOnBuild alapértelmezés szerint engedélyezve van fejlesztési módban, de kiadási módban le van tiltva:
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 { }
Az alábbi kód letiltja a ValidateScopes-t és a ValidateOnBuild-et a Development-ben.
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;
});
}
Lásd még
- minimális API-k rövid útmutatója
- OpenAPI-dokumentumok létrehozása
- Válaszok létrehozása minimális API-alkalmazásokban
- Szűrők minimális API-alkalmazásokban
- ASP.NET Core API-k hibáinak kezelése
- Hitelesítés és engedélyezés minimális API-kban
- Minimális API-alkalmazások tesztelése
- Rövid kapcsolatcsoportos útválasztás
- Identity API-végpontok
- kulcsalapú szolgáltatásfüggőség-injektálási tároló támogatása
- A minimális API-végpontok színfalak mögötti pillantása
- alapvető minimális API-k ASP.NET rendszerezése
- Fluent Validation-megbeszélés a GitHubon
Ez a dokumentum:
- Rövid útmutató a minimális API-khoz.
- Tapasztalt fejlesztőknek készült. Bevezetésként tekintse meg oktatóanyagot: Minimális API létrehozása ASP.NET Core.
A minimális API-k a következőkből állnak:
WebApplication
A következő kódot egy ASP.NET Core-sablon hozza létre:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző kód a parancssori dotnet new web vagy a Visual Studio Üres websablonjának kiválasztásával hozható létre.
A következő kód létrehoz egy WebApplication (app) anélkül, hogy explicit módon létrehoz egy WebApplicationBuilder:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create inicializálja a WebApplication osztály új példányát előre konfigurált alapértelmezett értékekkel.
WebApplication bizonyos feltételektől függően automatikusan hozzáadja a következő köztes szoftvereket a Minimal API-alkalmazásokhoz :
- Először hozzáadódik a
UseDeveloperExceptionPage, amikor aHostingEnvironment"Development". -
UseRoutingmásodikként kerül hozzáadásra, ha a felhasználói kód még nem hívta meg aUseRouting-et, és ha vannak konfigurált végpontok, példáulapp.MapGet. -
UseEndpointsa köztesréteg-folyamatok végéhez kerül hozzáadásra, ha bármelyik végpont konfigurálva van. -
UseAuthenticationazonnal hozzáadódikUseRoutingután, ha a felhasználói kód még nem hívta megUseAuthentication-t, és ha aIAuthenticationSchemeProviderészlelhető a szolgáltatónál.IAuthenticationSchemeProvideralapértelmezés szerintAddAuthenticationhasználatakor lesz hozzáadva, a szolgáltatások pedigIServiceProviderIsServicehasználatával észlelhetők. -
UseAuthorizationakkor lesz a következő, ha a felhasználói kód még nem hívta felUseAuthorization, ésIAuthorizationHandlerProviderészlelhető-e a szolgáltatóban.IAuthorizationHandlerProvideralapértelmezés szerintAddAuthorizationhasználatakor lesz hozzáadva, a szolgáltatások pedigIServiceProviderIsServicehasználatával észlelhetők. - A felhasználó által konfigurált köztes szoftver és végpontok
UseRoutingésUseEndpointsközé kerülnek.
Az alkalmazáshoz hozzáadott automatikus köztes szoftver gyakorlatilag a következő kódot eredményezi:
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 => {});
Bizonyos esetekben az alapértelmezett köztes szoftverkonfiguráció nem megfelelő az alkalmazáshoz, és módosítást igényel. Például a UseCors-t UseAuthentication és UseAuthorizationelőtt kell meghívni. Az alkalmazásnak meg kell hívnia UseAuthentication és UseAuthorization, ha UseCors van meghívva:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Ha a köztes szoftvereket az útvonalegyeztetés előtt kell futtatni, UseRouting kell meghívni, és a köztes szoftvernek a UseRoutinghívása előtt kell lennie. ebben az esetben nem szükséges UseEndpoints, mivel a korábban ismertetett módon automatikusan hozzáadja:
app.Use((context, next) =>
{
return next(context);
});
app.UseRouting();
// other middleware and endpoints
Terminál köztes szoftver hozzáadásakor:
- A köztes szoftvert
UseEndpointsután kell hozzáadni. - Az alkalmazásnak meg kell hívnia
UseRoutingésUseEndpoints, hogy a terminál közbenső szoftvere a megfelelő helyre kerüljön.
app.UseRouting();
app.MapGet("/", () => "hello world");
app.UseEndpoints(e => {});
app.Run(context =>
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
A terminál köztes szoftver olyan köztes szoftver, amely akkor fut, ha egyetlen végpont sem kezeli a kérést.
Portok használata
Amikor webalkalmazást hoz létre a Visual Studióval vagy dotnet new, létrejön egy Properties/launchSettings.json fájl, amely meghatározza azokat a portokat, amelyekre az alkalmazás válaszol. Az alábbi portbeállítási mintákban az alkalmazás Visual Studióból való futtatása hibaüzenetet ad vissza Unable to connect to web server 'AppName'. A Visual Studio hibát ad vissza, mert a Properties/launchSettings.jsonmegadott portot várja, de az alkalmazás a app.Run("http://localhost:3000")által megadott portot használja. Futtassa a következő portmódosítási mintákat a parancssorból.
Az alábbi szakaszok azt a portot állítják be, amelyekre az alkalmazás válaszol.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
Az előző kódban az alkalmazás reagál a 3000porton.
Több port
Az alábbi kódban az alkalmazás válaszol a port 3000 és 4000.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
A port beállítása a parancssorból
Az alábbi parancs lehetővé teszi, hogy az alkalmazás a 7777porton fogadjon.
dotnet run --urls="https://localhost:7777"
Ha a Kestrel végpont is konfigurálva van a appsettings.json fájlban, a appsettings.json megadott URL-címet használja a rendszer. További információért lásd: Kestrel végpont konfiguráció
A port beolvasása a környezetből
A következő kód beolvassa a portot a környezetből:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
A port környezetből való beállításának elsődleges módja a ASPNETCORE_URLS környezeti változó használata, amely az alábbi szakaszban látható.
Portok beállítása a ASPNETCORE_URLS környezeti változón keresztül
A port beállításához elérhető a ASPNETCORE_URLS környezeti változó:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS több URL-címet is támogat:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
Figyelés az összes felületen
Az alábbi minták azt mutatják be, hogy az összes felületen figyelnek
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();
Hallgatás minden felületen az ASPNETCORE_URLS használatával
Az előző minták használhatják a ASPNETCORE_URLS-t.
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
Figyeljen minden interfészen az ASPNETCORE_HTTPS_PORTS használatával
Az előző minták használhatják a ASPNETCORE_HTTPS_PORTS és ASPNETCORE_HTTP_PORTSkódokat.
ASPNETCORE_HTTP_PORTS=3000;5005
ASPNETCORE_HTTPS_PORTS=5000
További információ: Végpontok konfigurálása a ASP.NET Core Kestrel webkiszolgálóhoz
HTTPS beállítása fejlesztési tanúsítvánnyal
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
A fejlesztési tanúsítvánnyal kapcsolatos további információkért lásd: Az ASP.NET Core HTTPS fejlesztési tanúsítvány hitelesítése Windows és macOS.
HTTPS megadása egyéni tanúsítvány használatával
Az alábbi szakaszok bemutatják, hogyan adhatja meg az egyéni tanúsítványt a appsettings.json fájllal és konfigurációval.
Adja meg a testreszabott tanúsítványt a appsettings.json jelöléssel
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Az egyéni tanúsítvány megadása konfigurációval
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();
A tanúsítvány API-k használata
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();
A környezet olvasása
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();
További információ a környezet használatáról: ASP.NET Core futtatókörnyezetek
Configuration
A következő kód a konfigurációs rendszerből olvas be:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Config failed!";
app.MapGet("/", () => message);
app.Run();
További információ: ASP.NET Core konfiguráció
Logging
Az alábbi kód egy üzenetet ír az alkalmazás indítási naplójába:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
További információ: Naplózás a .NET-ben és a ASP.NET Core-ban
A függőség-injektálás (DI) konténer elérése
Az alábbi kód bemutatja, hogyan kérhet le szolgáltatásokat a DI-tárolóból az alkalmazás indításakor:
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();
Az alábbi kód bemutatja, hogyan érheti el a kulcsokat a DI-tárolóból a [FromKeyedServices] attribútum használatával:
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.";
}
További információ a DI-ről a Függőséginjektálás az ASP.NET Corecímű részben található.
WebApplicationBuilder
Ez a szakasz WebApplicationBuilderhasználatával tartalmaz mintakódot.
A tartalomgyöker, az alkalmazásnév és a környezet módosítása
A következő kód állítja be a tartalom gyökerét, az alkalmazás nevét és a környezetet:
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 inicializálja a WebApplicationBuilder osztály új példányát előre konfigurált alapértelmezett beállításokkal.
További információ: ASP.NET Alapvető alapismeretek áttekintése
A tartalomgyöker, az alkalmazás neve és a környezet módosítása környezeti változók vagy parancssor használatával
Az alábbi táblázat a tartalomgyöker, az alkalmazásnév és a környezet módosításához használt környezeti változót és parancssori argumentumot mutatja be:
| funkció | Környezet változó | Parancssori argumentum |
|---|---|---|
| Alkalmazás neve | ASPNETCORE_APPLICATIONNAME | --applicationName |
| Környezet neve | ASPNETCORE_ENVIRONMENT | --environment |
| Tartalomgyökér | ASPNETCORE_CONTENTROOT | --contentRoot |
Konfigurációszolgáltatók hozzáadása
Az alábbi minta hozzáadja az INI-konfigurációszolgáltatót:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Részletes információért lásd: Fájlkonfigurációs szolgáltatók az ASP.NET Core konfigurációjában.
Olvasási konfiguráció
Alapértelmezés szerint a WebApplicationBuilder több forrásból olvassa be a konfigurációt, beleértve a következőket:
-
appSettings.jsonésappSettings.{environment}.json - Környezeti változók
- A parancssor
A konfigurációs források teljes listáját a Alapértelmezett konfiguráció című részben találja, amely része a konfigurációnak az ASP.NET Coredokumentumban.
Az alábbi kód beolvassa HelloKey konfigurációból, és megjeleníti az értéket a / végponton. Ha a konfiguráció értéke null, a "Hello" messagevan hozzárendelve:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
A környezet olvasása
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsDevelopment())
{
Console.WriteLine($"Running in development.");
}
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Naplózási szolgáltatók hozzáadása
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();
Szolgáltatások hozzáadása
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();
Az IHostBuilder testreszabása
A IHostBuilder meglévő bővítési metódusok a Gazdagép tulajdonsághasználatával érhetők el.
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();
Az IWebHostBuilder testreszabása
A IWebHostBuilder bővítménymetelyek a WebApplicationBuilder.WebHost tulajdonság használatával érhetők el.
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();
Webes gyökér módosítása
Alapértelmezés szerint a webes gyökér a wwwroot mappában lévő tartalomgyökerhez képest van. A webes gyökér az, ahol a Statikus fájl köztes szoftver statikus fájlokat keres. A webes gyökér a WebHostOptions, a parancssor vagy a UseWebRoot metódus használatával módosítható:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Egyéni függőséginjektáló (DI) tároló
Az alábbi példa Autofachasznál:
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();
Köztes szoftver hozzáadása
Bármely meglévő ASP.NET Core middleware konfigurálható a WebApplication:
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
További információ: ASP.NET Core Middleware
Fejlesztői kivételoldal
WebApplication.CreateBuilder inicializálja a WebApplicationBuilder osztály új példányát előre konfigurált alapértelmezett értékekkel. A fejlesztői kivételoldal engedélyezve van az előre konfigurált alapértelmezett beállításokban. Ha a következő kódot a fejlesztési környezetben futtatja, a / navigálással egy barátságos oldal jelenik meg, ami megmutatja a kivételt.
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 Middleware
Az alábbi táblázat felsorolja a minimális API-kkal gyakran használt köztes szoftvereket.
| Middleware | Description | API |
|---|---|---|
| Authentication | Hitelesítési támogatást nyújt. | UseAuthentication |
| Authorization | Engedélyezési támogatást nyújt. | UseAuthorization |
| CORS | A forrásközi erőforrásmegosztást konfigurálja. | UseCors |
| Kivételkezelő | Globálisan kezeli a köztes szoftverfolyamat által kidobott kivételeket. | UseExceptionHandler |
| Továbbított fejlécek | Továbbítja a proxizott fejléceket az aktuális kérelemre. | UseForwardedHeaders |
| HTTPS-átirányítás | Átirányítja az összes HTTP-kérést a HTTPS-be. | UseHttpsRedirection |
| HTTP szigorú átviteli biztonsági (HSTS) | Biztonsági funkciókat javító middleware, amely egy speciális válaszfejlécet ad hozzá. | UseHsts |
| Kérelemnaplózás | TÁMOGATJA a HTTP-kérések és válaszok naplózását. | UseHttpLogging |
| Kérelem időtúllépései | Támogatja a kérések időtúllépéseinek konfigurálását, a globális alapértelmezett és végpontonkénti beállításokat. | UseRequestTimeouts |
| W3C-kérésnaplózás | Támogatja a HTTP-kérések és válaszok naplózását W3C formátumban. | UseW3CLogging |
| Válasz gyorsítótárazása | Támogatást nyújt a gyorsítótárazási válaszokhoz. | UseResponseCaching |
| Választömörítés | Támogatja a válaszok tömörítését. | UseResponseCompression |
| Session | Támogatást nyújt a felhasználói munkamenetek kezeléséhez. | UseSession |
| Statikus fájlok | Támogatja a statikus fájlok és a címtárböngészés kiszolgálását. | UseStaticFiles, UseFileServer |
| WebSockets | Engedélyezi a WebSockets protokollt. | UseWebSockets |
A következő szakaszok a kérések kezelését ismertetik: útválasztás, paraméterkötés és válaszok.
Routing
A konfigurált WebApplication támogatják a Map{Verb} és MapMethods, ahol a {Verb} egy teve-esetű HTTP-metódus, például Get, Post, Put vagy Delete:
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();
A metódusoknak átadott Delegate argumentumokat "útvonalkezelőknek" nevezzük.
Útvonalkezelők
Az útvonalkezelők olyan metódusok, amelyek az útvonal egyezésekor futnak. Az útvonalkezelők lehetnek lambdakifejezések, helyi függvények, példánymetódusok vagy statikus metódusok. Az útvonalkezelők lehetnek szinkronok vagy aszinkronok.
Lambda kifejezés
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();
Helyi függvény
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Példánymetódus
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";
}
}
Statikus metódus
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";
}
}
A Program.cs kívül definiált végpont
A minimális API-knak nem kell a(z) Program.cs-ban lennie.
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" });
});
}
}
Lásd még a később ebben a cikkben található Útvonalcsoportok részt.
Elnevezett végpontok és hivatkozás létrehozása
A végpontok nevet adhatnak a végpont URL-címeinek létrehozásához. A névvel ellátott végpontok használatával elkerülhető, hogy az alkalmazásokban ne kelljen kemény kódútvonalakat használni:
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();
Az előző kód megjeleníti a The link to the hello route is /hello-t a / végpontról.
MEGJEGYZÉS: A végpontok neve megkülönbözteti a kis- és nagybetűket.
Végpontnevek:
- Globálisan egyedinek kell lennie.
- OpenAPI-műveletazonosítóként használatos, ha az OpenAPI-támogatás engedélyezve van. További információ: OpenAPI.
Útvonalparaméterek
Az útvonalparaméterek az útvonalminta definíciójának részeként rögzíthetők:
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();
Az előző kód a The user id is 3 and book id is 7 értéket adja vissza az URI /users/3/books/7-ből.
Az útvonalkezelő deklarálhatja a rögzítendő paramétereket. Amikor egy olyan útvonalra irányuló kérést küld, amelynek a paraméterei rögzítésre vannak deklarálva, a rendszer elemzi és továbbítja a paramétereket a kezelőnek. Ez megkönnyíti az értékek biztonságos típusba rögzítését. Az előző kódban userId és bookId is int.
Az előző kódban, ha bármelyik útvonalértéket nem lehet int-é konvertálni, kivétel keletkezik. A GET kérés /users/hello/books/3 a következő kivételt okozza:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Helyettesítő karakter és az összes útvonal elfogása
A következő átfogó útvonal a "/posts/hello" végpontról Routing to hello-t ad vissza:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Útvonalkorlátozások
Az útvonalkorlátozások korlátozzák az útvonalak egyező viselkedését.
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();
Az alábbi táblázat az előző útvonalsablonokat és azok viselkedését mutatja be:
| Útvonalsablon | Példa egyező URI-ra |
|---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
További információért lásd: Útválasztási korlátozások hivatkozása a Útválasztás ASP.NET Corerészében.
Útvonalcsoportok
A MapGroup bővítménymetódus segít a végpontcsoportok közös előtaggal való rendszerezésében. Csökkenti az ismétlődő kódot, és lehetővé teszi a végpontok teljes csoportjainak testreszabását egyetlen hívással olyan metódusokhoz, mint a RequireAuthorization és WithMetadata, amelyek végpont metaadatait adják hozzá.
A következő kód például két hasonló végpontcsoportot hoz létre:
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;
}
Ebben a forgatókönyvben a Location fejléc relatív címét használhatja a 201 Created eredményben:
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
A végpontok első csoportja csak a /public/todos előtagú kéréseknek felel meg, és hitelesítés nélkül is elérhetők. A végpontok második csoportja csak a /private/todos előtagú kéréseknek felel meg, és hitelesítést igényel.
A QueryPrivateTodosvégpontszűrő-előállító egy helyi függvény, amely módosítja az útvonalkezelő TodoDb paramétereit annak érdekében, hogy lehetővé tegye a privát teendőadatok elérését és tárolását.
Az útvonalcsoportok a beágyazott csoportokat és az összetett előtagmintákat is támogatják útvonalparaméterekkel és korlátozásokkal. Az alábbi példában a user csoporthoz hozzárendelt útvonalkezelő rögzítheti a külső csoport előtagjaiban definiált {org} és {group} útvonalparamétereket.
Az előtag üres is lehet. Ez akkor lehet hasznos, ha végponti metaadatokat vagy szűrőket ad hozzá a végpontok egy csoportjához az útvonalminta módosítása nélkül.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
A szűrők vagy metaadatok csoporthoz való hozzáadása ugyanúgy viselkedik, mint az egyes végpontokhoz való egyenkénti hozzáadásuk, mielőtt további szűrőket vagy metaadatokat ad hozzá egy belső csoporthoz vagy adott végponthoz.
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);
});
A fenti példában a külső szűrő naplózza a bejövő kérést a belső szűrő előtt annak ellenére, hogy másodikként lett hozzáadva. Mivel a szűrők különböző csoportokra lettek alkalmazva, a egymáshoz viszonyított sorrend nem számít. A rendelésszűrők hozzáadásának sorrendje számít, ha ugyanarra a csoportra vagy egy adott végpontra alkalmazzák.
A /outer/inner/ kérés a következőket naplózza:
/outer group filter
/inner group filter
MapGet filter
Paraméterkötés
A paraméterkötés a kérelemadatok erősen gépelt paraméterekké alakításának folyamata, amelyeket az útvonalkezelők fejeznek ki. A kötési forrás határozza meg, hogy a paraméterek honnan vannak kötve. A kötési források lehetnek explicitek vagy következtethetők a HTTP-módszer és a paramétertípus alapján.
Támogatott kötési források:
- Útvonalértékek
- Lekérdezési karakterlánc
- Header
- Törzs (mint JSON)
- Űrlapértékek
- Függőséginjektálás által biztosított szolgáltatások
- Custom
A következő GET útvonalkezelő az alábbi paraméterkötési források némelyikét használja:
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 { }
Fő paraméterkötési funkciók
-
Explicit kötés: Használjon olyan attribútumokat, mint a
[FromRoute],[FromQuery],[FromHeader],[FromBody], ,[FromForm]és[FromServices]explicit módon adja meg a kötési forrásokat. -
Űrlapérték-kötés: Űrlapértékek kötése
[FromForm]attribútummal, beleértve a fájlfeltöltések támogatásátIFormFileésIFormFileCollection. - Összetett típusok: Gyűjteményekhez és összetett típusokhoz való kötés űrlapokból, lekérdezési sztringekből és fejlécekből.
- Egyéni kötés: Egyéni kötési logika implementálása a ,
TryParse, vagy aBindAsyncfelületen. - Választható paraméterek: Támogatja a null értékű típusokat és az opcionális paraméterek alapértelmezett értékeit.
- Függőséginjektálás: A paraméterek automatikusan kötődnek a DI-tárolóban regisztrált szolgáltatásokhoz.
-
Speciális típusok: Automatikus kötés a
HttpContext,HttpRequest,HttpResponse,CancellationToken,ClaimsPrincipalésStreamPipeReader.
Tudj meg többet: A paraméterkötéssel kapcsolatos részletes információkért, beleértve a speciális forgatókönyveket, az érvényesítést, a kötési elsőbbséget és a hibaelhárítást, tekintse meg a paraméterkötést a Minimal API-alkalmazásokban.
Responses
Az útvonalkezelők a következő típusú visszatérési értékeket támogatják:
-
IResultalapú – Ez magában foglalja aTask<IResult>-et és aValueTask<IResult>-t -
string– Ebbe beletartozikTask<string>ésValueTask<string> -
T(Bármilyen más típus) – Ebbe beletartozikTask<T>ésValueTask<T>
| Visszaadott érték | Behavior | Content-Type |
|---|---|---|
IResult |
A keretrendszer meghívja IResult.ExecuteAsync | A döntést a IResult végrehajtása hozta meg. |
string |
A keretrendszer közvetlenül a válaszba írja a sztringet | text/plain |
T (bármilyen más típus) |
A keretrendszer JSON-szerializálja a választ | application/json |
Az útvonalkezelő visszatérési értékeinek részletes útmutatója: Válaszok létrehozása minimális API-alkalmazásokban
Példa visszaadott értékekre
karakterlánc visszaadott értékei
app.MapGet("/hello", () => "Hello World");
JSON visszaadott értékek
app.MapGet("/hello", () => new { Message = "Hello World" });
TypedResults visszatérése
A következő kód egy TypedResultsad vissza:
app.MapGet("/hello", () => TypedResults.Ok(new Message() { Text = "Hello World!" }));
A TypedResults visszaadása előnyben részesíti a Resultsvisszatérését. További információ: TypedResults vs Results.
IResult visszatérési értékek
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Az alábbi példa a beépített eredménytípusokat használja a válasz testreszabásához:
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" }));
Egyéni állapotkód
app.MapGet("/405", () => Results.StatusCode(405));
Text
app.MapGet("/text", () => Results.Text("This is some text"));
Stream
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");
});
További példákért lásd Válaszok létrehozása minimal API-alkalmazásokban.
Redirect
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
File
app.MapGet("/download", () => Results.File("myfile.text"));
Beépített eredmények
A Results és TypedResults statikus osztályokban gyakori eredmény-segítők léteznek. A TypedResults visszaadása előnyben részesíti a Resultsvisszatérését. További információ: TypedResults vs Results.
Fejlécek módosítása
A válaszfejlécek módosításához használja a HttpResponse objektumot:
app.MapGet("/", (HttpContext context) => {
// Set a custom header
context.Response.Headers["X-Custom-Header"] = "CustomValue";
// Set a known header
context.Response.Headers.CacheControl = $"public,max-age=3600";
return "Hello World";
});
Eredmények testreszabása
Az alkalmazások egyéni IResult típus implementálásával szabályozhatják a válaszokat. Az alábbi kód egy PÉLDA EGY HTML-eredménytípusra:
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);
}
}
Javasoljuk, hogy adjon hozzá egy bővítménymetódust a Microsoft.AspNetCore.Http.IResultExtensions az egyéni eredmények felderíthetőbbé tétele érdekében.
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();
Beírt eredmények
A IResult felület olyan minimális API-kból visszaadott értékeket jelölhet, amelyek nem használják a JSON implicit támogatását a visszaadott objektum HTTP-válaszra való szerializálásához. A statikus Eredmények osztály különböző IResult típusú válaszok megjelenítésére szolgál. Például állítsa be a válaszállapot-kódot, vagy átirányítsa egy másik URL-címre.
A IResult implementáló típusok nyilvánosak, így teszteléskor lehetővé teszik a típusok helyességére vonatkozó állításokat. Például:
[TestClass()]
public class WeatherApiTests
{
[TestMethod()]
public void MapWeatherApiTest()
{
var result = WeatherApi.GetAllWeathers();
Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
}
}
A statikus TypedResults osztály megfelelő metódusainak visszatérési típusait megvizsgálva megtalálhatja azt a megfelelő nyilvános IResult típust, amelyre át lehet alakítani.
További példákért lásd Válaszok létrehozása minimal API-alkalmazásokban.
Filters
További információ: Szűrők a Minimális API-alkalmazásokban.
Authorization
Az útvonalak engedélyezési szabályzatokkal védhetők. Ezek deklarálhatók a [Authorize] attribútummal vagy a RequireAuthorization metódussal:
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();
Az előző kód így is írható RequireAuthorization:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Az alábbi minta a házirenden alapuló engedélyezés használatát mutatja be.
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();
Végpont elérésének engedélyezése hitelesítés nélküli felhasználók számára
A [AllowAnonymous] lehetővé teszi, hogy a hitelesítés nélküli felhasználók hozzáférjenek a végpontokhoz:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Az útvonalak CORS- engedélyezhetők CORS-szabályzatokkal. A CORS deklarálható a [EnableCors] attribútummal vagy a RequireCors metódussal. A következő minták engedélyezik a CORS-t:
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();
További információkért nézze meg: Kereszt-származási kérelmek engedélyezése (CORS) az ASP.NET Core
ValidateScopes és ValidateOnBuild
A ValidateScopes és a ValidateOnBuild alapértelmezés szerint engedélyezve vannak a Fejlesztési környezetben, de más környezetekben le vannak tiltva.
Ha ValidateOnBuildtrue, a DI-tároló ellenőrzi a szolgáltatás konfigurációját a létrehozáskor. Ha a szolgáltatáskonfiguráció érvénytelen, a build az alkalmazás indításakor meghiúsul, nem pedig futásidőben, amikor a szolgáltatást kérik.
Ha ValidateScopestrue, a DI-tároló ellenőrzi, hogy a hatókörrel rendelkező szolgáltatás nincs-e feloldva a gyökérhatókörből. A hatókörrel rendelkező szolgáltatás gyökérhatókörből való feloldása memóriavesztést okozhat, mivel a szolgáltatás a kérés hatókörénél hosszabb ideig marad a memóriában.
A ValidateScopes és a ValidateOnBuild alapértelmezés szerint hamisak a nem fejlesztési módban teljesítménybeli okokból.
Az alábbi kód azt mutatja, hogy a ValidateScopes alapértelmezés szerint engedélyezve van fejlesztési módban, de kiadási módban le van tiltva:
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 { }
Az alábbi kód azt mutatja, hogy a ValidateOnBuild alapértelmezés szerint engedélyezve van fejlesztési módban, de kiadási módban le van tiltva:
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 { }
Az alábbi kód letiltja a ValidateScopes-t és a ValidateOnBuild-et a Development-ben.
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;
});
}
Lásd még
- minimális API-k rövid útmutatója
- OpenAPI-dokumentumok létrehozása
- Válaszok létrehozása minimális API-alkalmazásokban
- Szűrők minimális API-alkalmazásokban
- ASP.NET Core API-k hibáinak kezelése
- Hitelesítés és engedélyezés minimális API-kban
- Minimális API-alkalmazások tesztelése
- Rövid kapcsolatcsoportos útválasztás
- Identity API-végpontok
- kulcsalapú szolgáltatásfüggőség-injektálási tároló támogatása
- A minimális API-végpontok színfalak mögötti pillantása
- alapvető minimális API-k ASP.NET rendszerezése
- Fluent Validation-megbeszélés a GitHubon
Ez a dokumentum:
- Rövid útmutató a minimális API-khoz.
- Tapasztalt fejlesztőknek készült. Bevezetésként tekintse meg oktatóanyagot: Minimális API létrehozása ASP.NET Core.
A minimális API-k a következőkből állnak:
WebApplication
A következő kódot egy ASP.NET Core-sablon hozza létre:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző kód a parancssori dotnet new web vagy a Visual Studio Üres websablonjának kiválasztásával hozható létre.
A következő kód létrehoz egy WebApplication (app) anélkül, hogy explicit módon létrehoz egy WebApplicationBuilder:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create inicializálja a WebApplication osztály új példányát előre konfigurált alapértelmezett értékekkel.
WebApplication bizonyos feltételektől függően automatikusan hozzáadja a következő köztes szoftvereket a Minimal API-alkalmazásokhoz :
- Először hozzáadódik a
UseDeveloperExceptionPage, amikor aHostingEnvironment"Development". -
UseRoutingmásodikként kerül hozzáadásra, ha a felhasználói kód még nem hívta meg aUseRouting-et, és ha vannak konfigurált végpontok, példáulapp.MapGet. -
UseEndpointsa köztesréteg-folyamatok végéhez kerül hozzáadásra, ha bármelyik végpont konfigurálva van. -
UseAuthenticationazonnal hozzáadódikUseRoutingután, ha a felhasználói kód még nem hívta megUseAuthentication-t, és ha aIAuthenticationSchemeProviderészlelhető a szolgáltatónál.IAuthenticationSchemeProvideralapértelmezés szerintAddAuthenticationhasználatakor lesz hozzáadva, a szolgáltatások pedigIServiceProviderIsServicehasználatával észlelhetők. -
UseAuthorizationakkor lesz a következő, ha a felhasználói kód még nem hívta felUseAuthorization, ésIAuthorizationHandlerProviderészlelhető-e a szolgáltatóban.IAuthorizationHandlerProvideralapértelmezés szerintAddAuthorizationhasználatakor lesz hozzáadva, a szolgáltatások pedigIServiceProviderIsServicehasználatával észlelhetők. - A felhasználó által konfigurált köztes szoftver és végpontok
UseRoutingésUseEndpointsközé kerülnek.
Az alkalmazáshoz hozzáadott automatikus köztes szoftver gyakorlatilag a következő kódot eredményezi:
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 => {});
Bizonyos esetekben az alapértelmezett köztes szoftverkonfiguráció nem megfelelő az alkalmazáshoz, és módosítást igényel. Például a UseCors-t UseAuthentication és UseAuthorizationelőtt kell meghívni. Az alkalmazásnak meg kell hívnia UseAuthentication és UseAuthorization, ha UseCors van meghívva:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Ha a köztes szoftvereket az útvonalegyeztetés előtt kell futtatni, UseRouting kell meghívni, és a köztes szoftvernek a UseRoutinghívása előtt kell lennie. ebben az esetben nem szükséges UseEndpoints, mivel a korábban ismertetett módon automatikusan hozzáadja:
app.Use((context, next) =>
{
return next(context);
});
app.UseRouting();
// other middleware and endpoints
Terminál köztes szoftver hozzáadásakor:
- A köztes szoftvert
UseEndpointsután kell hozzáadni. - Az alkalmazásnak meg kell hívnia
UseRoutingésUseEndpoints, hogy a terminál közbenső szoftvere a megfelelő helyre kerüljön.
app.UseRouting();
app.MapGet("/", () => "hello world");
app.UseEndpoints(e => {});
app.Run(context =>
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
A terminál köztes szoftver olyan köztes szoftver, amely akkor fut, ha egyetlen végpont sem kezeli a kérést.
Portok használata
Amikor webalkalmazást hoz létre a Visual Studióval vagy dotnet new, létrejön egy Properties/launchSettings.json fájl, amely meghatározza azokat a portokat, amelyekre az alkalmazás válaszol. Az alábbi portbeállítási mintákban az alkalmazás Visual Studióból való futtatása hibaüzenetet ad vissza Unable to connect to web server 'AppName'. A Visual Studio hibát ad vissza, mert a Properties/launchSettings.jsonmegadott portot várja, de az alkalmazás a app.Run("http://localhost:3000")által megadott portot használja. Futtassa a következő portmódosítási mintákat a parancssorból.
Az alábbi szakaszok azt a portot állítják be, amelyekre az alkalmazás válaszol.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
Az előző kódban az alkalmazás reagál a 3000porton.
Több port
Az alábbi kódban az alkalmazás válaszol a port 3000 és 4000.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
A port beállítása a parancssorból
Az alábbi parancs lehetővé teszi, hogy az alkalmazás a 7777porton fogadjon.
dotnet run --urls="https://localhost:7777"
Ha a Kestrel végpont is konfigurálva van a appsettings.json fájlban, a appsettings.json megadott URL-címet használja a rendszer. További információért lásd: Kestrel végpont konfiguráció
A port beolvasása a környezetből
A következő kód beolvassa a portot a környezetből:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
A port környezetből való beállításának elsődleges módja a ASPNETCORE_URLS környezeti változó használata, amely az alábbi szakaszban látható.
Portok beállítása a ASPNETCORE_URLS környezeti változón keresztül
A port beállításához elérhető a ASPNETCORE_URLS környezeti változó:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS több URL-címet is támogat:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
Figyelés az összes felületen
Az alábbi minták azt mutatják be, hogy az összes felületen figyelnek
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();
Hallgatás minden felületen az ASPNETCORE_URLS használatával
Az előző minták használhatják a ASPNETCORE_URLS-t.
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
Figyeljen minden interfészen az ASPNETCORE_HTTPS_PORTS használatával
Az előző minták használhatják a ASPNETCORE_HTTPS_PORTS és ASPNETCORE_HTTP_PORTSkódokat.
ASPNETCORE_HTTP_PORTS=3000;5005
ASPNETCORE_HTTPS_PORTS=5000
További információ: Végpontok konfigurálása a ASP.NET Core Kestrel webkiszolgálóhoz
HTTPS beállítása fejlesztési tanúsítvánnyal
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
A fejlesztési tanúsítvánnyal kapcsolatos további információkért lásd: Az ASP.NET Core HTTPS fejlesztési tanúsítvány hitelesítése Windows és macOS.
HTTPS megadása egyéni tanúsítvány használatával
Az alábbi szakaszok bemutatják, hogyan adhatja meg az egyéni tanúsítványt a appsettings.json fájllal és konfigurációval.
Adja meg a testreszabott tanúsítványt a appsettings.json jelöléssel
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Az egyéni tanúsítvány megadása konfigurációval
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();
A tanúsítvány API-k használata
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();
A környezet olvasása
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();
További információ a környezet használatáról: ASP.NET Core futtatókörnyezetek
Configuration
A következő kód a konfigurációs rendszerből olvas be:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Config failed!";
app.MapGet("/", () => message);
app.Run();
További információ: ASP.NET Core konfiguráció
Logging
Az alábbi kód egy üzenetet ír az alkalmazás indítási naplójába:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
További információ: Naplózás a .NET-ben és a ASP.NET Core-ban
A függőség-injektálás (DI) konténer elérése
Az alábbi kód bemutatja, hogyan kérhet le szolgáltatásokat a DI-tárolóból az alkalmazás indításakor:
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();
Az alábbi kód bemutatja, hogyan érheti el a kulcsokat a DI-tárolóból a [FromKeyedServices] attribútum használatával:
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.";
}
További információ a DI-ről a Függőséginjektálás az ASP.NET Corecímű részben található.
WebApplicationBuilder
Ez a szakasz WebApplicationBuilderhasználatával tartalmaz mintakódot.
A tartalomgyöker, az alkalmazásnév és a környezet módosítása
A következő kód állítja be a tartalom gyökerét, az alkalmazás nevét és a környezetet:
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 inicializálja a WebApplicationBuilder osztály új példányát előre konfigurált alapértelmezett beállításokkal.
További információ: ASP.NET Alapvető alapismeretek áttekintése
A tartalomgyöker, az alkalmazás neve és a környezet módosítása környezeti változók vagy parancssor használatával
Az alábbi táblázat a tartalomgyöker, az alkalmazásnév és a környezet módosításához használt környezeti változót és parancssori argumentumot mutatja be:
| funkció | Környezet változó | Parancssori argumentum |
|---|---|---|
| Alkalmazás neve | ASPNETCORE_APPLICATIONNAME | --applicationName |
| Környezet neve | ASPNETCORE_ENVIRONMENT | --environment |
| Tartalomgyökér | ASPNETCORE_CONTENTROOT | --contentRoot |
Konfigurációszolgáltatók hozzáadása
Az alábbi minta hozzáadja az INI-konfigurációszolgáltatót:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Részletes információért lásd: Fájlkonfigurációs szolgáltatók az ASP.NET Core konfigurációjában.
Olvasási konfiguráció
Alapértelmezés szerint a WebApplicationBuilder több forrásból olvassa be a konfigurációt, beleértve a következőket:
-
appSettings.jsonésappSettings.{environment}.json - Környezeti változók
- A parancssor
A konfigurációs források teljes listáját a Alapértelmezett konfiguráció című részben találja, amely része a konfigurációnak az ASP.NET Coredokumentumban.
Az alábbi kód beolvassa HelloKey konfigurációból, és megjeleníti az értéket a / végponton. Ha a konfiguráció értéke null, a "Hello" messagevan hozzárendelve:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
A környezet olvasása
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsDevelopment())
{
Console.WriteLine($"Running in development.");
}
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Naplózási szolgáltatók hozzáadása
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();
Szolgáltatások hozzáadása
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();
Az IHostBuilder testreszabása
A IHostBuilder meglévő bővítési metódusok a Gazdagép tulajdonsághasználatával érhetők el.
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();
Az IWebHostBuilder testreszabása
A IWebHostBuilder bővítménymetelyek a WebApplicationBuilder.WebHost tulajdonság használatával érhetők el.
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();
Webes gyökér módosítása
Alapértelmezés szerint a webes gyökér a wwwroot mappában lévő tartalomgyökerhez képest van. A webes gyökér az, ahol a Statikus fájl köztes szoftver statikus fájlokat keres. A webes gyökér a WebHostOptions, a parancssor vagy a UseWebRoot metódus használatával módosítható:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Egyéni függőséginjektáló (DI) tároló
Az alábbi példa Autofachasznál:
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();
Köztes szoftver hozzáadása
Bármely meglévő ASP.NET Core middleware konfigurálható a WebApplication:
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
További információ: ASP.NET Core Middleware
Fejlesztői kivételoldal
WebApplication.CreateBuilder inicializálja a WebApplicationBuilder osztály új példányát előre konfigurált alapértelmezett értékekkel. A fejlesztői kivételoldal engedélyezve van az előre konfigurált alapértelmezett beállításokban. Ha a következő kódot a fejlesztési környezetben futtatja, a / navigálással egy barátságos oldal jelenik meg, ami megmutatja a kivételt.
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 Middleware
Az alábbi táblázat felsorolja a minimális API-kkal gyakran használt köztes szoftvereket.
| Middleware | Description | API |
|---|---|---|
| Authentication | Hitelesítési támogatást nyújt. | UseAuthentication |
| Authorization | Engedélyezési támogatást nyújt. | UseAuthorization |
| CORS | A forrásközi erőforrásmegosztást konfigurálja. | UseCors |
| Kivételkezelő | Globálisan kezeli a köztes szoftverfolyamat által kidobott kivételeket. | UseExceptionHandler |
| Továbbított fejlécek | Továbbítja a proxizott fejléceket az aktuális kérelemre. | UseForwardedHeaders |
| HTTPS-átirányítás | Átirányítja az összes HTTP-kérést a HTTPS-be. | UseHttpsRedirection |
| HTTP szigorú átviteli biztonsági (HSTS) | Biztonsági funkciókat javító middleware, amely egy speciális válaszfejlécet ad hozzá. | UseHsts |
| Kérelemnaplózás | TÁMOGATJA a HTTP-kérések és válaszok naplózását. | UseHttpLogging |
| Kérelem időtúllépései | Támogatja a kérések időtúllépéseinek konfigurálását, a globális alapértelmezett és végpontonkénti beállításokat. | UseRequestTimeouts |
| W3C-kérésnaplózás | Támogatja a HTTP-kérések és válaszok naplózását W3C formátumban. | UseW3CLogging |
| Válasz gyorsítótárazása | Támogatást nyújt a gyorsítótárazási válaszokhoz. | UseResponseCaching |
| Választömörítés | Támogatja a válaszok tömörítését. | UseResponseCompression |
| Session | Támogatást nyújt a felhasználói munkamenetek kezeléséhez. | UseSession |
| Statikus fájlok | Támogatja a statikus fájlok és a címtárböngészés kiszolgálását. | UseStaticFiles, UseFileServer |
| WebSockets | Engedélyezi a WebSockets protokollt. | UseWebSockets |
A következő szakaszok a kérések kezelését ismertetik: útválasztás, paraméterkötés és válaszok.
Routing
A konfigurált WebApplication támogatják a Map{Verb} és MapMethods, ahol a {Verb} egy teve-esetű HTTP-metódus, például Get, Post, Put vagy Delete:
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();
A metódusoknak átadott Delegate argumentumokat "útvonalkezelőknek" nevezzük.
Útvonalkezelők
Az útvonalkezelők olyan metódusok, amelyek az útvonal egyezésekor futnak. Az útvonalkezelők lehetnek lambdakifejezések, helyi függvények, példánymetódusok vagy statikus metódusok. Az útvonalkezelők lehetnek szinkronok vagy aszinkronok.
Lambda kifejezés
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();
Helyi függvény
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Példánymetódus
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";
}
}
Statikus metódus
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";
}
}
A Program.cs kívül definiált végpont
A minimális API-knak nem kell a(z) Program.cs-ban lennie.
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" });
});
}
}
Lásd még a később ebben a cikkben található Útvonalcsoportok részt.
Elnevezett végpontok és hivatkozás létrehozása
A végpontok nevet adhatnak a végpont URL-címeinek létrehozásához. A névvel ellátott végpontok használatával elkerülhető, hogy az alkalmazásokban ne kelljen kemény kódútvonalakat használni:
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();
Az előző kód megjeleníti a The link to the hello route is /hello-t a / végpontról.
MEGJEGYZÉS: A végpontok neve megkülönbözteti a kis- és nagybetűket.
Végpontnevek:
- Globálisan egyedinek kell lennie.
- OpenAPI-műveletazonosítóként használatos, ha az OpenAPI-támogatás engedélyezve van. További információ: OpenAPI.
Útvonalparaméterek
Az útvonalparaméterek az útvonalminta definíciójának részeként rögzíthetők:
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();
Az előző kód a The user id is 3 and book id is 7 értéket adja vissza az URI /users/3/books/7-ből.
Az útvonalkezelő deklarálhatja a rögzítendő paramétereket. Amikor egy olyan útvonalra irányuló kérést küld, amelynek a paraméterei rögzítésre vannak deklarálva, a rendszer elemzi és továbbítja a paramétereket a kezelőnek. Ez megkönnyíti az értékek biztonságos típusba rögzítését. Az előző kódban userId és bookId is int.
Az előző kódban, ha bármelyik útvonalértéket nem lehet int-é konvertálni, kivétel keletkezik. A GET kérés /users/hello/books/3 a következő kivételt okozza:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Helyettesítő karakter és az összes útvonal elfogása
A következő átfogó útvonal a "/posts/hello" végpontról Routing to hello-t ad vissza:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Útvonalkorlátozások
Az útvonalkorlátozások korlátozzák az útvonalak egyező viselkedését.
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();
Az alábbi táblázat az előző útvonalsablonokat és azok viselkedését mutatja be:
| Útvonalsablon | Példa egyező URI-ra |
|---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
További információért lásd: Útválasztási korlátozások hivatkozása a Útválasztás ASP.NET Corerészében.
Útvonalcsoportok
A MapGroup bővítménymetódus segít a végpontcsoportok közös előtaggal való rendszerezésében. Csökkenti az ismétlődő kódot, és lehetővé teszi a végpontok teljes csoportjainak testreszabását egyetlen hívással olyan metódusokhoz, mint a RequireAuthorization és WithMetadata, amelyek végpont metaadatait adják hozzá.
A következő kód például két hasonló végpontcsoportot hoz létre:
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;
}
Ebben a forgatókönyvben a Location fejléc relatív címét használhatja a 201 Created eredményben:
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
A végpontok első csoportja csak a /public/todos előtagú kéréseknek felel meg, és hitelesítés nélkül is elérhetők. A végpontok második csoportja csak a /private/todos előtagú kéréseknek felel meg, és hitelesítést igényel.
A QueryPrivateTodosvégpontszűrő-előállító egy helyi függvény, amely módosítja az útvonalkezelő TodoDb paramétereit annak érdekében, hogy lehetővé tegye a privát teendőadatok elérését és tárolását.
Az útvonalcsoportok a beágyazott csoportokat és az összetett előtagmintákat is támogatják útvonalparaméterekkel és korlátozásokkal. Az alábbi példában a user csoporthoz hozzárendelt útvonalkezelő rögzítheti a külső csoport előtagjaiban definiált {org} és {group} útvonalparamétereket.
Az előtag üres is lehet. Ez akkor lehet hasznos, ha végponti metaadatokat vagy szűrőket ad hozzá a végpontok egy csoportjához az útvonalminta módosítása nélkül.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
A szűrők vagy metaadatok csoporthoz való hozzáadása ugyanúgy viselkedik, mint az egyes végpontokhoz való egyenkénti hozzáadásuk, mielőtt további szűrőket vagy metaadatokat ad hozzá egy belső csoporthoz vagy adott végponthoz.
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);
});
A fenti példában a külső szűrő naplózza a bejövő kérést a belső szűrő előtt annak ellenére, hogy másodikként lett hozzáadva. Mivel a szűrők különböző csoportokra lettek alkalmazva, a egymáshoz viszonyított sorrend nem számít. A rendelésszűrők hozzáadásának sorrendje számít, ha ugyanarra a csoportra vagy egy adott végpontra alkalmazzák.
A /outer/inner/ kérés a következőket naplózza:
/outer group filter
/inner group filter
MapGet filter
Paraméterkötés
A paraméterkötés a kérelemadatok erősen gépelt paraméterekké alakításának folyamata, amelyeket az útvonalkezelők fejeznek ki. A kötési forrás határozza meg, hogy a paraméterek honnan vannak kötve. A kötési források lehetnek explicitek vagy következtethetők a HTTP-módszer és a paramétertípus alapján.
Támogatott kötési források:
- Útvonalértékek
- Lekérdezési karakterlánc
- Header
- Törzs (mint JSON)
- Űrlapértékek
- Függőséginjektálás által biztosított szolgáltatások
- Custom
A következő GET útvonalkezelő az alábbi paraméterkötési források némelyikét használja:
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 { }
Fő paraméterkötési funkciók
-
Explicit kötés: Használjon olyan attribútumokat, mint a
[FromRoute],[FromQuery],[FromHeader],[FromBody], ,[FromForm]és[FromServices]explicit módon adja meg a kötési forrásokat. -
Űrlapérték-kötés: Űrlapértékek kötése
[FromForm]attribútummal, beleértve a fájlfeltöltések támogatásátIFormFileésIFormFileCollection. - Összetett típusok: Gyűjteményekhez és összetett típusokhoz való kötés űrlapokból, lekérdezési sztringekből és fejlécekből.
- Egyéni kötés: Egyéni kötési logika implementálása a ,
TryParse, vagy aBindAsyncfelületen. - Választható paraméterek: Támogatja a null értékű típusokat és az opcionális paraméterek alapértelmezett értékeit.
- Függőséginjektálás: A paraméterek automatikusan kötődnek a DI-tárolóban regisztrált szolgáltatásokhoz.
-
Speciális típusok: Automatikus kötés a
HttpContext,HttpRequest,HttpResponse,CancellationToken,ClaimsPrincipalésStreamPipeReader.
Tudj meg többet: A paraméterkötéssel kapcsolatos részletes információkért, beleértve a speciális forgatókönyveket, az érvényesítést, a kötési elsőbbséget és a hibaelhárítást, tekintse meg a paraméterkötést a Minimal API-alkalmazásokban.
Responses
Az útvonalkezelők a következő típusú visszatérési értékeket támogatják:
-
IResultalapú – Ez magában foglalja aTask<IResult>-et és aValueTask<IResult>-t -
string– Ebbe beletartozikTask<string>ésValueTask<string> -
T(Bármilyen más típus) – Ebbe beletartozikTask<T>ésValueTask<T>
| Visszaadott érték | Behavior | Content-Type |
|---|---|---|
IResult |
A keretrendszer meghívja IResult.ExecuteAsync | A döntést a IResult végrehajtása hozta meg. |
string |
A keretrendszer közvetlenül a válaszba írja a sztringet | text/plain |
T (bármilyen más típus) |
A keretrendszer JSON-szerializálja a választ | application/json |
Az útvonalkezelő visszatérési értékeinek részletes útmutatója: Válaszok létrehozása minimális API-alkalmazásokban
Példa visszaadott értékekre
karakterlánc visszaadott értékei
app.MapGet("/hello", () => "Hello World");
JSON visszaadott értékek
app.MapGet("/hello", () => new { Message = "Hello World" });
TypedResults visszatérése
A következő kód egy TypedResultsad vissza:
app.MapGet("/hello", () => TypedResults.Ok(new Message() { Text = "Hello World!" }));
A TypedResults visszaadása előnyben részesíti a Resultsvisszatérését. További információ: TypedResults vs Results.
IResult visszatérési értékek
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Az alábbi példa a beépített eredménytípusokat használja a válasz testreszabásához:
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" }));
Egyéni állapotkód
app.MapGet("/405", () => Results.StatusCode(405));
Text
app.MapGet("/text", () => Results.Text("This is some text"));
Stream
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");
});
További példákért lásd Válaszok létrehozása minimal API-alkalmazásokban.
Redirect
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
File
app.MapGet("/download", () => Results.File("myfile.text"));
Beépített eredmények
A Results és TypedResults statikus osztályokban gyakori eredmény-segítők léteznek. A TypedResults visszaadása előnyben részesíti a Resultsvisszatérését. További információ: TypedResults vs Results.
Fejlécek módosítása
A válaszfejlécek módosításához használja a HttpResponse objektumot:
app.MapGet("/", (HttpContext context) => {
// Set a custom header
context.Response.Headers["X-Custom-Header"] = "CustomValue";
// Set a known header
context.Response.Headers.CacheControl = $"public,max-age=3600";
return "Hello World";
});
Eredmények testreszabása
Az alkalmazások egyéni IResult típus implementálásával szabályozhatják a válaszokat. Az alábbi kód egy PÉLDA EGY HTML-eredménytípusra:
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);
}
}
Javasoljuk, hogy adjon hozzá egy bővítménymetódust a Microsoft.AspNetCore.Http.IResultExtensions az egyéni eredmények felderíthetőbbé tétele érdekében.
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();
Beírt eredmények
A IResult felület olyan minimális API-kból visszaadott értékeket jelölhet, amelyek nem használják a JSON implicit támogatását a visszaadott objektum HTTP-válaszra való szerializálásához. A statikus Eredmények osztály különböző IResult típusú válaszok megjelenítésére szolgál. Például állítsa be a válaszállapot-kódot, vagy átirányítsa egy másik URL-címre.
A IResult implementáló típusok nyilvánosak, így teszteléskor lehetővé teszik a típusok helyességére vonatkozó állításokat. Például:
[TestClass()]
public class WeatherApiTests
{
[TestMethod()]
public void MapWeatherApiTest()
{
var result = WeatherApi.GetAllWeathers();
Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
}
}
A statikus TypedResults osztály megfelelő metódusainak visszatérési típusait megvizsgálva megtalálhatja azt a megfelelő nyilvános IResult típust, amelyre át lehet alakítani.
További példákért lásd Válaszok létrehozása minimal API-alkalmazásokban.
Filters
További információ: Szűrők a Minimális API-alkalmazásokban.
Authorization
Az útvonalak engedélyezési szabályzatokkal védhetők. Ezek deklarálhatók a [Authorize] attribútummal vagy a RequireAuthorization metódussal:
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();
Az előző kód így is írható RequireAuthorization:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Az alábbi minta a házirenden alapuló engedélyezés használatát mutatja be.
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();
Végpont elérésének engedélyezése hitelesítés nélküli felhasználók számára
A [AllowAnonymous] lehetővé teszi, hogy a hitelesítés nélküli felhasználók hozzáférjenek a végpontokhoz:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Az útvonalak CORS- engedélyezhetők CORS-szabályzatokkal. A CORS deklarálható a [EnableCors] attribútummal vagy a RequireCors metódussal. A következő minták engedélyezik a CORS-t:
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();
További információkért nézze meg: Kereszt-származási kérelmek engedélyezése (CORS) az ASP.NET Core
ValidateScopes és ValidateOnBuild
A ValidateScopes és a ValidateOnBuild alapértelmezés szerint engedélyezve vannak a Fejlesztési környezetben, de más környezetekben le vannak tiltva.
Ha ValidateOnBuildtrue, a DI-tároló ellenőrzi a szolgáltatás konfigurációját a létrehozáskor. Ha a szolgáltatáskonfiguráció érvénytelen, a build az alkalmazás indításakor meghiúsul, nem pedig futásidőben, amikor a szolgáltatást kérik.
Ha ValidateScopestrue, a DI-tároló ellenőrzi, hogy a hatókörrel rendelkező szolgáltatás nincs-e feloldva a gyökérhatókörből. A hatókörrel rendelkező szolgáltatás gyökérhatókörből való feloldása memóriavesztést okozhat, mivel a szolgáltatás a kérés hatókörénél hosszabb ideig marad a memóriában.
A ValidateScopes és a ValidateOnBuild alapértelmezés szerint hamisak a nem fejlesztési módban teljesítménybeli okokból.
Az alábbi kód azt mutatja, hogy a ValidateScopes alapértelmezés szerint engedélyezve van fejlesztési módban, de kiadási módban le van tiltva:
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 { }
Az alábbi kód azt mutatja, hogy a ValidateOnBuild alapértelmezés szerint engedélyezve van fejlesztési módban, de kiadási módban le van tiltva:
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 { }
Az alábbi kód letiltja a ValidateScopes-t és a ValidateOnBuild-et a Development-ben.
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;
});
}
Lásd még
- minimális API-k rövid útmutatója
- OpenAPI-dokumentumok létrehozása
- Válaszok létrehozása minimális API-alkalmazásokban
- Szűrők minimális API-alkalmazásokban
- ASP.NET Core API-k hibáinak kezelése
- Hitelesítés és engedélyezés minimális API-kban
- Minimális API-alkalmazások tesztelése
- Rövid kapcsolatcsoportos útválasztás
- Identity API-végpontok
- kulcsalapú szolgáltatásfüggőség-injektálási tároló támogatása
- A minimális API-végpontok színfalak mögötti pillantása
- alapvető minimális API-k ASP.NET rendszerezése
- Fluent Validation-megbeszélés a GitHubon
Ez a dokumentum:
- Rövid útmutató a minimális API-khoz.
- Tapasztalt fejlesztőknek készült. Bevezetésként tekintse meg oktatóanyagot: Minimális API létrehozása ASP.NET Core
A minimális API-k a következőkből állnak:
WebApplication
A következő kódot egy ASP.NET Core-sablon hozza létre:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző kód a parancssori dotnet new web vagy a Visual Studio Üres websablonjának kiválasztásával hozható létre.
A következő kód létrehoz egy WebApplication (app) anélkül, hogy explicit módon létrehoz egy WebApplicationBuilder:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create inicializálja a WebApplication osztály új példányát előre konfigurált alapértelmezett értékekkel.
WebApplication bizonyos feltételektől függően automatikusan hozzáadja a következő köztes szoftvereket a Minimal API-alkalmazásokhoz :
- Először hozzáadódik a
UseDeveloperExceptionPage, amikor aHostingEnvironment"Development". -
UseRoutingmásodikként kerül hozzáadásra, ha a felhasználói kód még nem hívta meg aUseRouting-et, és ha vannak konfigurált végpontok, példáulapp.MapGet. -
UseEndpointsa köztesréteg-folyamatok végéhez kerül hozzáadásra, ha bármelyik végpont konfigurálva van. -
UseAuthenticationazonnal hozzáadódikUseRoutingután, ha a felhasználói kód még nem hívta megUseAuthentication-t, és ha aIAuthenticationSchemeProviderészlelhető a szolgáltatónál.IAuthenticationSchemeProvideralapértelmezés szerintAddAuthenticationhasználatakor lesz hozzáadva, a szolgáltatások pedigIServiceProviderIsServicehasználatával észlelhetők. -
UseAuthorizationakkor lesz a következő, ha a felhasználói kód még nem hívta felUseAuthorization, ésIAuthorizationHandlerProviderészlelhető-e a szolgáltatóban.IAuthorizationHandlerProvideralapértelmezés szerintAddAuthorizationhasználatakor lesz hozzáadva, a szolgáltatások pedigIServiceProviderIsServicehasználatával észlelhetők. - A felhasználó által konfigurált köztes szoftver és végpontok
UseRoutingésUseEndpointsközé kerülnek.
Az alkalmazáshoz hozzáadott automatikus köztes szoftver gyakorlatilag a következő kódot eredményezi:
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 => {});
Bizonyos esetekben az alapértelmezett köztes szoftverkonfiguráció nem megfelelő az alkalmazáshoz, és módosítást igényel. Például a UseCors-t UseAuthentication és UseAuthorizationelőtt kell meghívni. Az alkalmazásnak meg kell hívnia UseAuthentication és UseAuthorization, ha UseCors van meghívva:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Ha a köztes szoftvereket az útvonalegyeztetés előtt kell futtatni, UseRouting kell meghívni, és a köztes szoftvernek a UseRoutinghívása előtt kell lennie. ebben az esetben nem szükséges UseEndpoints, mivel a korábban ismertetett módon automatikusan hozzáadja:
app.Use((context, next) =>
{
return next(context);
});
app.UseRouting();
// other middleware and endpoints
Terminál köztes szoftver hozzáadásakor:
- A köztes szoftvert
UseEndpointsután kell hozzáadni. - Az alkalmazásnak meg kell hívnia
UseRoutingésUseEndpoints, hogy a terminál közbenső szoftvere a megfelelő helyre kerüljön.
app.UseRouting();
app.MapGet("/", () => "hello world");
app.UseEndpoints(e => {});
app.Run(context =>
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
A terminál köztes szoftver olyan köztes szoftver, amely akkor fut, ha egyetlen végpont sem kezeli a kérést.
Portok használata
Amikor webalkalmazást hoz létre a Visual Studióval vagy dotnet new, létrejön egy Properties/launchSettings.json fájl, amely meghatározza azokat a portokat, amelyekre az alkalmazás válaszol. Az alábbi portbeállítási mintákban az alkalmazás Visual Studióból való futtatása hibaüzenetet ad vissza Unable to connect to web server 'AppName'. A Visual Studio hibát ad vissza, mert a Properties/launchSettings.jsonmegadott portot várja, de az alkalmazás a app.Run("http://localhost:3000")által megadott portot használja. Futtassa a következő portmódosítási mintákat a parancssorból.
Az alábbi szakaszok azt a portot állítják be, amelyekre az alkalmazás válaszol.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
Az előző kódban az alkalmazás reagál a 3000porton.
Több port
Az alábbi kódban az alkalmazás válaszol a port 3000 és 4000.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
A port beállítása a parancssorból
Az alábbi parancs lehetővé teszi, hogy az alkalmazás a 7777porton fogadjon.
dotnet run --urls="https://localhost:7777"
Ha a Kestrel végpont is konfigurálva van a appsettings.json fájlban, a appsettings.json megadott URL-címet használja a rendszer. További információért lásd: Kestrel végpont konfiguráció
A port beolvasása a környezetből
A következő kód beolvassa a portot a környezetből:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
A port környezetből való beállításának elsődleges módja a ASPNETCORE_URLS környezeti változó használata, amely az alábbi szakaszban látható.
Portok beállítása a ASPNETCORE_URLS környezeti változón keresztül
A port beállításához elérhető a ASPNETCORE_URLS környezeti változó:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS több URL-címet is támogat:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
További információ a környezet használatáról: ASP.NET Core futtatókörnyezetek
Figyelés az összes felületen
Az alábbi minták azt mutatják be, hogy az összes felületen figyelnek
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();
Hallgatás minden felületen az ASPNETCORE_URLS használatával
Az előző minták használhatják a ASPNETCORE_URLS-t.
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
HTTPS beállítása fejlesztési tanúsítvánnyal
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
A fejlesztési tanúsítvánnyal kapcsolatos további információkért lásd: Az ASP.NET Core HTTPS fejlesztési tanúsítvány hitelesítése Windows és macOS.
HTTPS megadása egyéni tanúsítvány használatával
Az alábbi szakaszok bemutatják, hogyan adhatja meg az egyéni tanúsítványt a appsettings.json fájllal és konfigurációval.
Adja meg a testreszabott tanúsítványt a appsettings.json jelöléssel
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Az egyéni tanúsítvány megadása konfigurációval
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();
A tanúsítvány API-k használata
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();
Configuration
A következő kód a konfigurációs rendszerből olvas be:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Config failed!";
app.MapGet("/", () => message);
app.Run();
További információ: ASP.NET Core konfiguráció
Logging
Az alábbi kód egy üzenetet ír az alkalmazás indítási naplójába:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
További információ: Naplózás a .NET-ben és a ASP.NET Core-ban
A függőség-injektálás (DI) konténer elérése
Az alábbi kód bemutatja, hogyan kérhet le szolgáltatásokat a DI-tárolóból az alkalmazás indításakor:
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();
További információ: Függőséginjektálás az ASP.NET Core-ban.
WebApplicationBuilder
Ez a szakasz WebApplicationBuilderhasználatával tartalmaz mintakódot.
A tartalomgyöker, az alkalmazásnév és a környezet módosítása
A következő kód állítja be a tartalom gyökerét, az alkalmazás nevét és a környezetet:
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 inicializálja a WebApplicationBuilder osztály új példányát előre konfigurált alapértelmezett beállításokkal.
További információ: ASP.NET Alapvető alapismeretek áttekintése
A tartalomgyöker, az alkalmazásnév és a környezet módosítása környezeti változók vagy parancssor szerint
Az alábbi táblázat a tartalomgyöker, az alkalmazásnév és a környezet módosításához használt környezeti változót és parancssori argumentumot mutatja be:
| funkció | Környezet változó | Parancssori argumentum |
|---|---|---|
| Alkalmazás neve | ASPNETCORE_APPLICATIONNAME | --applicationName |
| Környezet neve | ASPNETCORE_ENVIRONMENT | --environment |
| Tartalomgyökér | ASPNETCORE_CONTENTROOT | --contentRoot |
Konfigurációszolgáltatók hozzáadása
Az alábbi minta hozzáadja az INI-konfigurációszolgáltatót:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Részletes információért lásd: Fájlkonfigurációs szolgáltatók az ASP.NET Core konfigurációjában.
Olvasási konfiguráció
Alapértelmezés szerint a WebApplicationBuilder több forrásból olvassa be a konfigurációt, beleértve a következőket:
-
appSettings.jsonésappSettings.{environment}.json - Környezeti változók
- A parancssor
Az alábbi kód beolvassa HelloKey konfigurációból, és megjeleníti az értéket a / végponton. Ha a konfiguráció értéke null, a "Hello" messagevan hozzárendelve:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
A konfigurációs források teljes listáját az Alapértelmezett konfiguráció szakaszban találja az ASP.NET Core konfiguráció című dokumentumban.
Naplózási szolgáltatók hozzáadása
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();
Szolgáltatások hozzáadása
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();
Az IHostBuilder testreszabása
A IHostBuilder meglévő bővítési metódusok a Gazdagép tulajdonsághasználatával érhetők el.
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();
Az IWebHostBuilder testreszabása
A IWebHostBuilder bővítménymetelyek a WebApplicationBuilder.WebHost tulajdonság használatával érhetők el.
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();
Webes gyökér módosítása
Alapértelmezés szerint a webes gyökér a wwwroot mappában lévő tartalomgyökerhez képest van. A webes gyökér az, ahol a Statikus fájl köztes szoftver statikus fájlokat keres. A webes gyökér a WebHostOptions, a parancssor vagy a UseWebRoot metódus használatával módosítható:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Egyéni függőséginjektáló (DI) tároló
Az alábbi példa Autofachasznál:
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();
Köztes szoftver hozzáadása
Bármely meglévő ASP.NET Core middleware konfigurálható a WebApplication:
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
További információ: ASP.NET Core Middleware
Fejlesztői kivételoldal
WebApplication.CreateBuilder inicializálja a WebApplicationBuilder osztály új példányát előre konfigurált alapértelmezett értékekkel. A fejlesztői kivételoldal engedélyezve van az előre konfigurált alapértelmezett beállításokban. Ha a következő kódot a fejlesztési környezetben futtatja, a / navigálással egy barátságos oldal jelenik meg, ami megmutatja a kivételt.
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 Middleware
Az alábbi táblázat felsorolja a minimális API-kkal gyakran használt köztes szoftvereket.
| Middleware | Description | API |
|---|---|---|
| Authentication | Hitelesítési támogatást nyújt. | UseAuthentication |
| Authorization | Engedélyezési támogatást nyújt. | UseAuthorization |
| CORS | A forrásközi erőforrásmegosztást konfigurálja. | UseCors |
| Kivételkezelő | Globálisan kezeli a köztes szoftverfolyamat által kidobott kivételeket. | UseExceptionHandler |
| Továbbított fejlécek | Továbbítja a proxizott fejléceket az aktuális kérelemre. | UseForwardedHeaders |
| HTTPS-átirányítás | Átirányítja az összes HTTP-kérést a HTTPS-be. | UseHttpsRedirection |
| HTTP szigorú átviteli biztonsági (HSTS) | Biztonsági funkciókat javító middleware, amely egy speciális válaszfejlécet ad hozzá. | UseHsts |
| Kérelemnaplózás | TÁMOGATJA a HTTP-kérések és válaszok naplózását. | UseHttpLogging |
| Kérelem időtúllépései | Támogatja a kérések időtúllépéseinek konfigurálását, a globális alapértelmezett és végpontonkénti beállításokat. | UseRequestTimeouts |
| W3C-kérésnaplózás | Támogatja a HTTP-kérések és válaszok naplózását W3C formátumban. | UseW3CLogging |
| Válasz gyorsítótárazása | Támogatást nyújt a gyorsítótárazási válaszokhoz. | UseResponseCaching |
| Választömörítés | Támogatja a válaszok tömörítését. | UseResponseCompression |
| Session | Támogatást nyújt a felhasználói munkamenetek kezeléséhez. | UseSession |
| Statikus fájlok | Támogatja a statikus fájlok és a címtárböngészés kiszolgálását. | UseStaticFiles, UseFileServer |
| WebSockets | Engedélyezi a WebSockets protokollt. | UseWebSockets |
A következő szakaszok a kérések kezelését ismertetik: útválasztás, paraméterkötés és válaszok.
Routing
A konfigurált WebApplication támogatják a Map{Verb} és MapMethods, ahol a {Verb} egy teve-esetű HTTP-metódus, például Get, Post, Put vagy Delete:
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();
A metódusoknak átadott Delegate argumentumokat "útvonalkezelőknek" nevezzük.
Útvonalkezelők
Az útvonalkezelők olyan metódusok, amelyek az útvonal egyezésekor futnak. Az útvonalkezelők lehetnek lambdakifejezések, helyi függvények, példánymetódusok vagy statikus metódusok. Az útvonalkezelők lehetnek szinkronok vagy aszinkronok.
Lambda kifejezés
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();
Helyi függvény
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Példánymetódus
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";
}
}
Statikus metódus
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";
}
}
A Program.cs kívül definiált végpont
A minimális API-knak nem kell a(z) Program.cs-ban lennie.
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" });
});
}
}
Lásd még a később ebben a cikkben található Útvonalcsoportok részt.
Elnevezett végpontok és hivatkozás létrehozása
A végpontok nevet adhatnak a végpont URL-címeinek létrehozásához. A névvel ellátott végpontok használatával elkerülhető, hogy az alkalmazásokban ne kelljen kemény kódútvonalakat használni:
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();
Az előző kód megjeleníti a The link to the hello route is /hello-t a / végpontról.
MEGJEGYZÉS: A végpontok neve megkülönbözteti a kis- és nagybetűket.
Végpontnevek:
- Globálisan egyedinek kell lennie.
- OpenAPI-műveletazonosítóként használatos, ha az OpenAPI-támogatás engedélyezve van. További információ: OpenAPI.
Útvonalparaméterek
Az útvonalparaméterek az útvonalminta definíciójának részeként rögzíthetők:
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();
Az előző kód a The user id is 3 and book id is 7 értéket adja vissza az URI /users/3/books/7-ből.
Az útvonalkezelő deklarálhatja a rögzítendő paramétereket. Amikor egy olyan útvonalra irányuló kérést küld, amelynek a paraméterei rögzítésre vannak deklarálva, a rendszer elemzi és továbbítja a paramétereket a kezelőnek. Ez megkönnyíti az értékek biztonságos típusba rögzítését. Az előző kódban userId és bookId is int.
Az előző kódban, ha bármelyik útvonalértéket nem lehet int-é konvertálni, kivétel keletkezik. A GET kérés /users/hello/books/3 a következő kivételt okozza:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Helyettesítő karakter és az összes útvonal elfogása
A következő átfogó útvonal a "/posts/hello" végpontról Routing to hello-t ad vissza:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Útvonalkorlátozások
Az útvonalkorlátozások korlátozzák az útvonalak egyező viselkedését.
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();
Az alábbi táblázat az előző útvonalsablonokat és azok viselkedését mutatja be:
| Útvonalsablon | Példa egyező URI-ra |
|---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
További információért lásd: Útválasztási korlátozások hivatkozása a Útválasztás ASP.NET Corerészében.
Útvonalcsoportok
A MapGroup bővítménymetódus segít a végpontcsoportok közös előtaggal való rendszerezésében. Csökkenti az ismétlődő kódot, és lehetővé teszi a végpontok teljes csoportjainak testreszabását egyetlen hívással olyan metódusokhoz, mint a RequireAuthorization és WithMetadata, amelyek végpont metaadatait adják hozzá.
A következő kód például két hasonló végpontcsoportot hoz létre:
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;
}
Ebben a forgatókönyvben a Location fejléc relatív címét használhatja a 201 Created eredményben:
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
A végpontok első csoportja csak a /public/todos előtagú kéréseknek felel meg, és hitelesítés nélkül is elérhetők. A végpontok második csoportja csak a /private/todos előtagú kéréseknek felel meg, és hitelesítést igényel.
A QueryPrivateTodosvégpontszűrő-előállító egy helyi függvény, amely módosítja az útvonalkezelő TodoDb paramétereit annak érdekében, hogy lehetővé tegye a privát teendőadatok elérését és tárolását.
Az útvonalcsoportok a beágyazott csoportokat és az összetett előtagmintákat is támogatják útvonalparaméterekkel és korlátozásokkal. Az alábbi példában a user csoporthoz hozzárendelt útvonalkezelő rögzítheti a külső csoport előtagjaiban definiált {org} és {group} útvonalparamétereket.
Az előtag üres is lehet. Ez akkor lehet hasznos, ha végponti metaadatokat vagy szűrőket ad hozzá a végpontok egy csoportjához az útvonalminta módosítása nélkül.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
A szűrők vagy metaadatok csoporthoz való hozzáadása ugyanúgy viselkedik, mint az egyes végpontokhoz való egyenkénti hozzáadásuk, mielőtt további szűrőket vagy metaadatokat ad hozzá egy belső csoporthoz vagy adott végponthoz.
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);
});
A fenti példában a külső szűrő naplózza a bejövő kérést a belső szűrő előtt annak ellenére, hogy másodikként lett hozzáadva. Mivel a szűrők különböző csoportokra lettek alkalmazva, a egymáshoz viszonyított sorrend nem számít. A rendelésszűrők hozzáadásának sorrendje számít, ha ugyanarra a csoportra vagy egy adott végpontra alkalmazzák.
A /outer/inner/ kérés a következőket naplózza:
/outer group filter
/inner group filter
MapGet filter
Paraméterkötés
A paraméterkötés a kérelemadatok erősen gépelt paraméterekké alakításának folyamata, amelyeket az útvonalkezelők fejeznek ki. A kötési forrás határozza meg, hogy a paraméterek honnan vannak kötve. A kötési források lehetnek explicitek vagy következtethetők a HTTP-módszer és a paramétertípus alapján.
Támogatott kötési források:
- Útvonalértékek
- Lekérdezési karakterlánc
- Header
- Törzs (mint JSON)
- Függőséginjektálás által biztosított szolgáltatások
- Custom
Az űrlapértékek kötése nem natívan támogatott .NET 6 és 7 rendszerben.
Az alábbi GET útvonalkezelő az alábbi paraméterkötési források némelyikét használja:
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 { }
Az alábbi táblázat az előző példában használt paraméterek és a kapcsolódó kötési források közötti kapcsolatot mutatja be.
| Parameter | Kötés forrása |
|---|---|
id |
útvonal értéke |
page |
lekérdezési sztring |
customHeader |
fejléc |
service |
Függőséginjektálás által biztosított |
A HTTP-metódusok GET, HEAD, OPTIONSés DELETE nem kötődnek implicit módon a törzsből. A HTTP-metódusok törzséből (JSON-ként) való kötéshez kifejezetten[FromBody] vagy a HttpRequestolvasásához.
Az alábbi példában a POST útvonalkezelő egy kötési törzsforrást (JSON-ként) használ a person paraméterhez:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/", (Person person) => { });
record Person(string Name, int Age);
Az előző példákban szereplő paraméterek automatikusan kötődnek a kérelemadatokhoz. A paraméterkötés által biztosított kényelem bemutatásához az alábbi útvonalkezelők bemutatják, hogyan olvashatók be közvetlenül a kérelem adatai a kérelemből:
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>();
// ...
});
Explicit paraméterkötés
Az attribútumokkal explicit módon deklarálható, hogy a paraméterek honnan vannak kötve.
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);
| Parameter | Kötés forrása |
|---|---|
id |
útvonalérték id |
page |
lekérdezési karakterlánc "p" nevű |
service |
Függőséginjektálás által biztosított |
contentType |
fejléc a "Content-Type" névvel |
Note
Az űrlapértékek kötése nem natívan támogatott .NET 6 és 7 rendszerben.
Paraméterkötés függőséginjektálással
A minimális API-k paraméterkötése függőséginjektálási köti a paramétereket, ha a típus szolgáltatásként van konfigurálva. Nem szükséges explicit módon alkalmazni a [FromServices] attribútumot egy paraméterre. A következő kódban mindkét művelet az időt adja vissza:
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();
Választható paraméterek
Az útvonalkezelőkben deklarált paramétereket a rendszer szükség szerint kezeli:
- Ha egy kérelem megfelel az útvonalnak, az útvonalkezelő csak akkor fut, ha a kérelemben minden szükséges paraméter meg van adva.
- Ha nem adja meg az összes szükséges paramétert, az hibát eredményez.
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 visszaadott |
/products |
BadHttpRequestException: A szükséges "int pageNumber" paraméter nem lett megadva a lekérdezési sztringből. |
/products/1 |
HTTP 404-es hiba, nincs egyező útvonal |
Ha a pageNumber nem kötelezővé szeretné tenni, adja meg a típust opcionálisként, vagy adjon meg egy alapértelmezett értéket:
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 visszaadott |
/products |
1 visszaadott |
/products2 |
1 visszaadott |
Az előző null értékű és alapértelmezett érték az összes forrásra vonatkozik:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/products", (Product? product) => { });
app.Run();
Az előző kód null értékű termékkel hívja meg a metódust, ha nem küldenek kéréstörzset.
MEGJEGYZÉS: Ha érvénytelen adatokat ad meg, és a paraméter nullázható, az útvonalkezelő nem kerül végrehajtásra.
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 visszaérkezett |
/products |
1 visszaérkezett |
/products?pageNumber=two |
BadHttpRequestException: Nem sikerült megkötni a "Nullable<int> pageNumber" paramétert a "kettő" értékből. |
/products/two |
HTTP 404-es hiba, nincs egyező útvonal |
További információt a kötési hibák szakaszban talál.
Speciális típusok
A következő típusok explicit attribútumok nélkül vannak megkötve:
HttpContext: Az aktuális HTTP-kéréssel vagy -válaszsal kapcsolatos összes információt tartalmazó környezet:
app.MapGet("/", (HttpContext context) => context.Response.WriteAsync("Hello World"));HttpRequest és HttpResponse: A HTTP-kérés és a HTTP-válasz:
app.MapGet("/", (HttpRequest request, HttpResponse response) => response.WriteAsync($"Hello World {request.Query["name"]}"));CancellationToken: Az aktuális HTTP-kéréshez társított törlési token:
app.MapGet("/", async (CancellationToken cancellationToken) => await MakeLongRunningRequestAsync(cancellationToken));ClaimsPrincipal: A kérelemhez társított felhasználó, HttpContext.User:
app.MapGet("/", (ClaimsPrincipal user) => user.Identity.Name);
A kérelem törzsét kössük össze Stream vagy PipeReader-ként.
A kérelem törzse Stream vagy PipeReader-ként összekapcsolható, hogy hatékonyan támogassa azokat a forgatókönyveket, amelyekben a felhasználónak adatokat kell feldolgoznia, és:
- Tárolja az adatokat blobtárolóba, vagy az adatokat egy üzenetsor-szolgáltatóhoz csatolja.
- Feldolgozhatja a tárolt adatokat egy feldolgozói folyamattal vagy egy felhőfüggvénnyel.
Előfordulhat például, hogy az adatok Azure Queue Storage- vagy Azure Blob Storage-tárolóba kerülnek.
A következő kód egy háttér-üzenetsort implementál:
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 következő kód hozzárendeli a kérelem törzsét egy Stream-hoz:
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);
});
Az alábbi kód a teljes Program.cs fájlt jeleníti meg:
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();
- Az adatok olvasásakor a
Streamugyanaz az objektum, mintHttpRequest.Body. - A kérelem törzse alapértelmezés szerint nincs pufferelve. A test elolvasása után nem lehet újraindítani. A stream nem olvasható többször.
- A
Streamés aPipeReadernem használhatók a minimális műveletkezelőn kívül, mivel a mögöttes puffereket a rendszer megsemmisíti vagy újra felhasználja.
Fájlfeltöltések az IFormFile és az IFormFileCollection használatával
A következő kód IFormFile és IFormFileCollection használ a fájl feltöltéséhez:
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();
A hitelesített fájlfeltöltési kérelmek egy Engedélyezési fejléc, ügyféltanúsítványvagy cookie fejléc használatával támogatottak.
A .NET 7-ben a ASP.NET Core nem támogatja az antiforgery beépített támogatását.
Az Antiforgery a ASP.NET Core-ban érhető el a .NET 8-ban vagy újabb verzióiban . Azonban a IAntiforgery szolgáltatáshasználatával implementálható.
Tömbök és karakterláncértékek összekapcsolása fejlécekből és kérdésláncokból
Az alábbi kód bemutatja, hogyan lehet a lekérdezési karakterláncokat primitív típusokba, karakterlánctömbökbe és StringValuestömbbe kötni.
// 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]}");
A lekérdezési sztringek vagy fejlécértékek összetett típusú tömbhöz való kötése akkor támogatott, ha a típus TryParse implementálva van. A következő kód egy sztringtömbhöz kötődik, és a megadott címkékkel rendelkező összes elemet visszaadja:
// 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();
});
Az alábbi kód a modellt és a szükséges TryParse implementációt mutatja be:
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 következő kód egy int tömbhöz kapcsolódik:
// 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();
});
Az előző kód teszteléséhez adja hozzá a következő végpontot az adatbázis Todo elemekkel való feltöltéséhez:
// POST /todoitems/batch
app.MapPost("/todoitems/batch", async (Todo[] todos, TodoDb db) =>
{
await db.Todos.AddRangeAsync(todos);
await db.SaveChangesAsync();
return Results.Ok(todos);
});
Használjon egy API-tesztelési eszközt, például HttpRepl a következő adatok átadásához az előző végpontnak:
[
{
"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 következő kód a fejléckulcshoz X-Todo-Id kapcsolódik, és visszaadja a Todo elemeket az egyező Id értékekkel:
// 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();
});
Note
Ha egy string[] egy lekérdezési sztringből illeszt, az egyező lekérdezési sztringérték hiánya null érték helyett üres tömböt eredményez.
Paraméterkötés az [AsParameters] argumentumlistákhoz
AsParametersAttribute egyszerű paraméterkötést tesz lehetővé a típusokhoz, nem pedig összetett vagy rekurzív modellkötéshez.
Vegye figyelembe a következő kódot:
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.
Fontolja meg a következő GET végpontot:
app.MapGet("/todoitems/{id}",
async (int Id, TodoDb Db) =>
await Db.Todos.FindAsync(Id)
is Todo todo
? Results.Ok(new TodoItemDTO(todo))
: Results.NotFound());
Az alábbi struct helyettesítheti az előző kiemelt paramétereket:
struct TodoItemRequest
{
public int Id { get; set; }
public TodoDb Db { get; set; }
}
Az átszervezett GET végpont az előző struct-et használja az AsParameters attribútummal.
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());
Az alábbi kód további végpontokat jelenít meg az alkalmazásban:
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();
});
A paraméterlisták újrabontásához a következő osztályok használhatók:
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!;
}
Az alábbi kód a AsParameters és az előtte lévő struct valamint osztályok használatával átszervezett végpontokat mutatja be.
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();
});
Az alábbi record típusokkal helyettesítheti az előző paramétereket:
record TodoItemRequest(int Id, TodoDb Db);
record CreateTodoItemRequest(TodoItemDTO Dto, TodoDb Db);
record EditTodoItemRequest(int Id, TodoItemDTO Dto, TodoDb Db);
A structAsParameters-gyel való használata hatékonyabb lehet, mint egy record típus használata.
A teljes mintakód az AspNetCore.Docs.Samples adattárban.
Egyéni kötés
A paraméterkötés testreszabásának három módja van:
- Az útvonal-, lekérdezés- és fejléckötési forrásokhoz az egyéni típusok kötéséhez adjon hozzá egy statikus
TryParsemetódust a típushoz. - A kötési folyamat szabályozása egy
BindAsyncmetódus típuson való implementálásával. - Speciális forgatókönyvek esetén a IBindableFromHttpContext<TSelf> interfész implementálásával biztosítsa az egyéni kötési logikát közvetlenül a
HttpContext-ből.
TryParse
TryParse két API-val rendelkezik:
public static bool TryParse(string value, out T result);
public static bool TryParse(string value, IFormatProvider provider, out T result);
Az alábbi kód a Point: 12.3, 10.1 kódot jeleníti meg az URI /map?Point=12.3,10.1-el.
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 következő API-kkal rendelkezik:
public static ValueTask<T?> BindAsync(HttpContext context, ParameterInfo parameter);
public static ValueTask<T?> BindAsync(HttpContext context);
Az alábbi kód a SortBy:xyz, SortDirection:Desc, CurrentPage:99 kódot jeleníti meg az URI /products?SortBy=xyz&SortDir=Desc&Page=99-el.
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
}
Egyéni paraméterkötés a IBindableFromHttpContext használatával.
ASP.NET Core támogatja az egyéni paraméterkötést minimális API-kban az IBindableFromHttpContext<TSelf> interfész használatával. Ez a C# 11 statikus absztrakt tagjaival bevezetett felület lehetővé teszi, hogy olyan típusokat hozzon létre, amelyek közvetlenül az útvonalkezelő paraméterekben köthetők http-környezetből.
public interface IBindableFromHttpContext<TSelf>
where TSelf : class, IBindableFromHttpContext<TSelf>
{
static abstract ValueTask<TSelf?> BindAsync(HttpContext context, ParameterInfo parameter);
}
Az IBindableFromHttpContext<TSelf> interfész implementálásával egyéni típusokat hozhat létre, amelyek saját kötési logikájuk kezeléséhez használják a HttpContextet. Ha egy útvonalkezelő tartalmaz egy ilyen típusú paramétert, a keretrendszer automatikusan meghívja a statikus BindAsync metódust a példány létrehozásához:
using CustomBindingExample;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpsRedirection();
app.MapGet("/", () => "Hello, IBindableFromHttpContext example!");
app.MapGet("/custom-binding", (CustomBoundParameter param) =>
{
return $"Value from custom binding: {param.Value}";
});
app.MapGet("/combined/{id}", (int id, CustomBoundParameter param) =>
{
return $"ID: {id}, Custom Value: {param.Value}";
});
Az alábbi példa egy HTTP-fejlécből kötődő egyéni paraméter implementációját mutatja be:
using System.Reflection;
namespace CustomBindingExample;
public class CustomBoundParameter : IBindableFromHttpContext<CustomBoundParameter>
{
public string Value { get; init; } = default!;
public static ValueTask<CustomBoundParameter?> BindAsync(HttpContext context, ParameterInfo parameter)
{
// Custom binding logic here
// This example reads from a custom header
var value = context.Request.Headers["X-Custom-Header"].ToString();
// If no header was provided, you could fall back to a query parameter
if (string.IsNullOrEmpty(value))
{
value = context.Request.Query["customValue"].ToString();
}
return ValueTask.FromResult<CustomBoundParameter?>(new CustomBoundParameter
{
Value = value
});
}
}
Az érvényesítést az egyéni kötési logikán belül is megvalósíthatja:
app.MapGet("/validated", (ValidatedParameter param) =>
{
if (string.IsNullOrEmpty(param.Value))
{
return Results.BadRequest("Value cannot be empty");
}
return Results.Ok($"Validated value: {param.Value}");
});
A mintakód megtekintése vagy letöltése (letöltés)
Kötési hibák
Ha a kötés sikertelen, a keretrendszer hibakeresési üzenetet naplóz, és a hibamódtól függően különböző állapotkódokat ad vissza az ügyfélnek.
| Hiba mód | Null értékű paraméter típusa | Kötés forrása | Állapotkód |
|---|---|---|---|
{ParameterType}.TryParse visszaad false |
yes | route/query/header | 400 |
{ParameterType}.BindAsync visszaad null |
yes | custom | 400 |
{ParameterType}.BindAsync dobások |
nem számít | custom | 500 |
| A JSON-törzs deszerializálásának sikertelensége | nem számít | body | 400 |
Helytelen tartalomtípus (nem application/json) |
nem számít | body | 415 |
Kötési elsőbbség
A kötési forrás paraméterből való meghatározásának szabályai:
- A paraméteren (From* attribútumokon) definiált explicit attribútum a következő sorrendben:
- Útvonalértékek:
[FromRoute] - Lekérdezési karakterlánc:
[FromQuery] - Fejléc:
[FromHeader] - Törzs:
[FromBody] - Szolgáltatás:
[FromServices] - Paraméterértékek:
[AsParameters]
- Útvonalértékek:
- Speciális típusok
HttpContext-
HttpRequest(HttpContext.Request) -
HttpResponse(HttpContext.Response) -
ClaimsPrincipal(HttpContext.User) -
CancellationToken(HttpContext.RequestAborted) -
IFormFileCollection(HttpContext.Request.Form.Files) -
IFormFile(HttpContext.Request.Form.Files[paramName]) -
Stream(HttpContext.Request.Body) -
PipeReader(HttpContext.Request.BodyReader)
- A paramétertípus érvényes statikus
BindAsyncmetódussal rendelkezik. - A paraméter típusa sztring, vagy érvényes statikus
TryParsemetódussal rendelkezik.- Ha a paraméter neve megtalálható az útvonalsablonban. A
app.Map("/todo/{id}", (int id) => {});idaz útvonalhoz van kötve. - Lekérdezési karakterláncból kötve.
- Ha a paraméter neve megtalálható az útvonalsablonban. A
- Ha a paramétertípus egy függőséginjektálás által biztosított szolgáltatás, akkor ezt a szolgáltatást használja forrásként.
- A paraméter a törzsből származik.
JSON deszerializálási beállítások konfigurálása a törzskötéshez
A testkötési forrás System.Text.Json-t használ a deszerializáláshoz. Ezt az alapértelmezett beállítást nem lehet módosítani, de a JSON szerializálási és deszerializálási beállításai konfigurálhatók.
JSON deszerializálási beállítások konfigurálása globálisan
Az alkalmazásokra globálisan érvényes beállítások ConfigureHttpJsonOptionsmeghívásával konfigurálhatók. Az alábbi példa a nyilvános mezőket és a JSON-kimenet formátumát tartalmazza.
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
// }
Mivel a mintakód szerializálást és deszerializálást is konfigurál, képes olvasni NameField, és NameField belefoglalni a kimeneti JSON-fájlba.
JSON-deszerializálási beállítások konfigurálása végponthoz
ReadFromJsonAsync-nak vannak túlterhelései, amelyek JsonSerializerOptions objektumot fogadnak el. Az alábbi példa a nyilvános mezőket és a JSON-kimenet formátumát tartalmazza.
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
// }
Mivel az előző kód csak a deszerializálásra alkalmazza a testre szabott beállításokat, a kimeneti JSON kizárja NameField.
Olvassa el a kérés törzsét
Olvassa el a kérelem törzsét közvetlenül egy HttpContext vagy HttpRequest paraméter használatával:
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();
Az előző kód:
- A kérelmi törzshöz a HttpRequest.BodyReaderhasználatával fér hozzá.
- Másolja a kérelem törzsét egy helyi fájlba.
Responses
Az útvonalkezelők a következő típusú visszatérési értékeket támogatják:
-
IResultalapú – Ez magában foglalja aTask<IResult>-et és aValueTask<IResult>-t -
string– Ebbe beletartozikTask<string>ésValueTask<string> -
T(Bármilyen más típus) – Ebbe beletartozikTask<T>ésValueTask<T>
| Visszaadott érték | Behavior | Content-Type |
|---|---|---|
IResult |
A keretrendszer meghívja IResult.ExecuteAsync | A döntést a IResult végrehajtása hozta meg. |
string |
A keretrendszer közvetlenül a válaszba írja a sztringet | text/plain |
T (bármilyen más típus) |
A keretrendszer JSON-szerializálja a választ | application/json |
Az útvonalkezelő visszatérési értékeinek részletes útmutatója: Válaszok létrehozása minimális API-alkalmazásokban
Példa visszaadott értékekre
karakterlánc visszaadott értékei
app.MapGet("/hello", () => "Hello World");
JSON visszaadott értékek
app.MapGet("/hello", () => new { Message = "Hello World" });
TypedResults visszatérése
A következő kód egy TypedResultsad vissza:
app.MapGet("/hello", () => TypedResults.Ok(new Message() { Text = "Hello World!" }));
A TypedResults visszaadása előnyben részesíti a Resultsvisszatérését. További információ: TypedResults vs Results.
IResult visszatérési értékek
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Az alábbi példa a beépített eredménytípusokat használja a válasz testreszabásához:
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" }));
Egyéni állapotkód
app.MapGet("/405", () => Results.StatusCode(405));
Text
app.MapGet("/text", () => Results.Text("This is some text"));
Stream
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");
});
További példákért lásd Válaszok létrehozása minimal API-alkalmazásokban.
Redirect
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
File
app.MapGet("/download", () => Results.File("myfile.text"));
Beépített eredmények
A Results és TypedResults statikus osztályokban gyakori eredmény-segítők léteznek. A TypedResults visszaadása előnyben részesíti a Resultsvisszatérését. További információ: TypedResults vs Results.
Eredmények testreszabása
Az alkalmazások egyéni IResult típus implementálásával szabályozhatják a válaszokat. Az alábbi kód egy PÉLDA EGY HTML-eredménytípusra:
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);
}
}
Javasoljuk, hogy adjon hozzá egy bővítménymetódust a Microsoft.AspNetCore.Http.IResultExtensions az egyéni eredmények felderíthetőbbé tétele érdekében.
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();
Beírt eredmények
A IResult felület olyan minimális API-kból visszaadott értékeket jelölhet, amelyek nem használják a JSON implicit támogatását a visszaadott objektum HTTP-válaszra való szerializálásához. A statikus Eredmények osztály különböző IResult típusú válaszok megjelenítésére szolgál. Például állítsa be a válaszállapot-kódot, vagy átirányítsa egy másik URL-címre.
A IResult implementáló típusok nyilvánosak, így teszteléskor lehetővé teszik a típusok helyességére vonatkozó állításokat. Például:
[TestClass()]
public class WeatherApiTests
{
[TestMethod()]
public void MapWeatherApiTest()
{
var result = WeatherApi.GetAllWeathers();
Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
}
}
A statikus TypedResults osztály megfelelő metódusainak visszatérési típusait megvizsgálva megtalálhatja azt a megfelelő nyilvános IResult típust, amelyre át lehet alakítani.
További példákért lásd Válaszok létrehozása minimal API-alkalmazásokban.
Filters
Lásd: Szűrők a Minimális API-alkalmazásokban
Authorization
Az útvonalak engedélyezési szabályzatokkal védhetők. Ezek deklarálhatók a [Authorize] attribútummal vagy a RequireAuthorization metódussal:
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();
Az előző kód így is írható RequireAuthorization:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Az alábbi minta a házirenden alapuló engedélyezés használatát mutatja be.
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();
Végpont elérésének engedélyezése hitelesítés nélküli felhasználók számára
A [AllowAnonymous] lehetővé teszi, hogy a hitelesítés nélküli felhasználók hozzáférjenek a végpontokhoz:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Az útvonalak CORS- engedélyezhetők CORS-szabályzatokkal. A CORS deklarálható a [EnableCors] attribútummal vagy a RequireCors metódussal. A következő minták engedélyezik a CORS-t:
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();
További információkért nézze meg: Kereszt-származási kérelmek engedélyezése (CORS) az ASP.NET Core
Lásd még
Ez a dokumentum:
- Rövid útmutató a minimális API-khoz.
- Tapasztalt fejlesztőknek készült. Bevezetésként tekintse meg oktatóanyagot: Minimális API létrehozása ASP.NET Core
A minimális API-k a következőkből állnak:
- WebApplication és WebApplicationBuilder
- Útvonalkezelők
WebApplication
A következő kódot egy ASP.NET Core-sablon hozza létre:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Az előző kód a parancssori dotnet new web vagy a Visual Studio Üres websablonjának kiválasztásával hozható létre.
A következő kód létrehoz egy WebApplication (app) anélkül, hogy explicit módon létrehoz egy WebApplicationBuilder:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create inicializálja a WebApplication osztály új példányát előre konfigurált alapértelmezett értékekkel.
Portok használata
Amikor webalkalmazást hoz létre a Visual Studióval vagy dotnet new, létrejön egy Properties/launchSettings.json fájl, amely meghatározza azokat a portokat, amelyekre az alkalmazás válaszol. Az alábbi portbeállítási mintákban az alkalmazás Visual Studióból való futtatása hibaüzenetet ad vissza Unable to connect to web server 'AppName'. Futtassa a következő portmódosítási mintákat a parancssorból.
Az alábbi szakaszok azt a portot állítják be, amelyekre az alkalmazás válaszol.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
Az előző kódban az alkalmazás reagál a 3000porton.
Több port
Az alábbi kódban az alkalmazás válaszol a port 3000 és 4000.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
A port beállítása a parancssorból
Az alábbi parancs lehetővé teszi, hogy az alkalmazás a 7777porton fogadjon.
dotnet run --urls="https://localhost:7777"
Ha a Kestrel végpont is konfigurálva van a appsettings.json fájlban, a appsettings.json megadott URL-címet használja a rendszer. További információért lásd: Kestrel végpont konfiguráció
A port beolvasása a környezetből
A következő kód beolvassa a portot a környezetből:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
A port környezetből való beállításának elsődleges módja a ASPNETCORE_URLS környezeti változó használata, amely az alábbi szakaszban látható.
Portok beállítása a ASPNETCORE_URLS környezeti változón keresztül
A port beállításához elérhető a ASPNETCORE_URLS környezeti változó:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS több URL-címet is támogat:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
Figyelés az összes felületen
Az alábbi minták azt mutatják be, hogy az összes felületen figyelnek
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();
Hallgatás minden felületen az ASPNETCORE_URLS használatával
Az előző minták használhatják a ASPNETCORE_URLS-t.
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
HTTPS beállítása fejlesztési tanúsítvánnyal
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
A fejlesztési tanúsítvánnyal kapcsolatos további információkért lásd: Az ASP.NET Core HTTPS fejlesztési tanúsítvány hitelesítése Windows és macOS.
HTTPS megadása egyéni tanúsítvány használatával
Az alábbi szakaszok bemutatják, hogyan adhatja meg az egyéni tanúsítványt a appsettings.json fájllal és konfigurációval.
Adja meg a testreszabott tanúsítványt a appsettings.json jelöléssel
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Az egyéni tanúsítvány megadása konfigurációval
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();
A tanúsítvány API-k használata
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();
A környezet olvasása
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();
További információ a környezet használatáról: ASP.NET Core futtatókörnyezetek
Configuration
A következő kód a konfigurációs rendszerből olvas be:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Hello";
app.MapGet("/", () => message);
app.Run();
További információ: ASP.NET Core konfiguráció
Logging
Az alábbi kód egy üzenetet ír az alkalmazás indítási naplójába:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
További információ: Naplózás a .NET-ben és a ASP.NET Core-ban
A függőség-injektálás (DI) konténer elérése
Az alábbi kód bemutatja, hogyan kérhet le szolgáltatásokat a DI-tárolóból az alkalmazás indításakor:
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();
További információ: Függőséginjektálás az ASP.NET Core-ban.
WebApplicationBuilder
Ez a szakasz WebApplicationBuilderhasználatával tartalmaz mintakódot.
A tartalomgyöker, az alkalmazásnév és a környezet módosítása
A következő kód állítja be a tartalom gyökerét, az alkalmazás nevét és a környezetet:
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 inicializálja a WebApplicationBuilder osztály új példányát előre konfigurált alapértelmezett beállításokkal.
További információ: ASP.NET Alapvető alapismeretek áttekintése
A tartalomgyöker, az alkalmazásnév és a környezet módosítása környezeti változók vagy parancssor szerint
Az alábbi táblázat a tartalomgyöker, az alkalmazásnév és a környezet módosításához használt környezeti változót és parancssori argumentumot mutatja be:
| funkció | Környezet változó | Parancssori argumentum |
|---|---|---|
| Alkalmazás neve | ASPNETCORE_APPLICATIONNAME | --applicationName |
| Környezet neve | ASPNETCORE_ENVIRONMENT | --environment |
| Tartalomgyökér | ASPNETCORE_CONTENTROOT | --contentRoot |
Konfigurációszolgáltatók hozzáadása
Az alábbi minta hozzáadja az INI-konfigurációszolgáltatót:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Részletes információért lásd: Fájlkonfigurációs szolgáltatók az ASP.NET Core konfigurációjában.
Olvasási konfiguráció
Alapértelmezés szerint a WebApplicationBuilder több forrásból olvassa be a konfigurációt, beleértve a következőket:
-
appSettings.jsonésappSettings.{environment}.json - Környezeti változók
- A parancssor
A konfigurációs források teljes listáját az Alapértelmezett konfiguráció szakaszban találja az ASP.NET Core konfiguráció című dokumentumban.
Az alábbi kód beolvassa HelloKey konfigurációból, és megjeleníti az értéket a / végponton. Ha a konfiguráció értéke null, a "Hello" messagevan hozzárendelve:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
A környezet olvasása
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
Naplózási szolgáltatók hozzáadása
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();
Szolgáltatások hozzáadása
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();
Az IHostBuilder testreszabása
A IHostBuilder meglévő bővítési metódusok a Gazdagép tulajdonsághasználatával érhetők el.
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();
Az IWebHostBuilder testreszabása
A IWebHostBuilder bővítménymetelyek a WebApplicationBuilder.WebHost tulajdonság használatával érhetők el.
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();
Webes gyökér módosítása
Alapértelmezés szerint a webes gyökér a wwwroot mappában lévő tartalomgyökerhez képest van. A webes gyökér az, ahol a Statikus fájl köztes szoftver statikus fájlokat keres. A webes gyökér a WebHostOptions, a parancssor vagy a UseWebRoot metódus használatával módosítható:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Egyéni függőséginjektáló (DI) tároló
Az alábbi példa Autofachasznál:
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();
Köztes szoftver hozzáadása
Bármely meglévő ASP.NET Core middleware konfigurálható a WebApplication:
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
További információ: ASP.NET Core Middleware
Fejlesztői kivételoldal
WebApplication.CreateBuilder inicializálja a WebApplicationBuilder osztály új példányát előre konfigurált alapértelmezett értékekkel. A fejlesztői kivételoldal engedélyezve van az előre konfigurált alapértelmezett beállításokban. Ha a következő kódot a fejlesztési környezetben futtatja, a / navigálással egy barátságos oldal jelenik meg, ami megmutatja a kivételt.
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 Middleware
Az alábbi táblázat felsorolja a minimális API-kkal gyakran használt köztes szoftvereket.
| Middleware | Description | API |
|---|---|---|
| Authentication | Hitelesítési támogatást nyújt. | UseAuthentication |
| Authorization | Engedélyezési támogatást nyújt. | UseAuthorization |
| CORS | A forrásközi erőforrásmegosztást konfigurálja. | UseCors |
| Kivételkezelő | Globálisan kezeli a köztes szoftverfolyamat által kidobott kivételeket. | UseExceptionHandler |
| Továbbított fejlécek | Továbbítja a proxizott fejléceket az aktuális kérelemre. | UseForwardedHeaders |
| HTTPS-átirányítás | Átirányítja az összes HTTP-kérést a HTTPS-be. | UseHttpsRedirection |
| HTTP szigorú átviteli biztonsági (HSTS) | Biztonsági funkciókat javító middleware, amely egy speciális válaszfejlécet ad hozzá. | UseHsts |
| Kérelemnaplózás | TÁMOGATJA a HTTP-kérések és válaszok naplózását. | UseHttpLogging |
| W3C-kérésnaplózás | Támogatja a HTTP-kérések és válaszok naplózását W3C formátumban. | UseW3CLogging |
| Válasz gyorsítótárazása | Támogatást nyújt a gyorsítótárazási válaszokhoz. | UseResponseCaching |
| Választömörítés | Támogatja a válaszok tömörítését. | UseResponseCompression |
| Session | Támogatást nyújt a felhasználói munkamenetek kezeléséhez. | UseSession |
| Statikus fájlok | Támogatja a statikus fájlok és a címtárböngészés kiszolgálását. | UseStaticFiles, UseFileServer |
| WebSockets | Engedélyezi a WebSockets protokollt. | UseWebSockets |
Kérések kezelése
A következő szakaszok az útválasztást, a paraméterkötést és a válaszokat ismertetik.
Routing
A konfigurált WebApplication támogatja Map{Verb} és MapMethods:
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();
Útvonalkezelők
Az útvonalkezelők olyan metódusok, amelyek az útvonal egyezésekor futnak. Az útvonalkezelők bármilyen típusú függvények lehetnek, beleértve a szinkron és aszinkron függvényeket is. Az útvonalkezelők lehetnek lambdakifejezések, helyi függvények, példánymetódusok vagy statikus metódusok.
Lambda kifejezés
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();
Helyi függvény
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Példánymetódus
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";
}
}
Statikus metódus
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";
}
}
Elnevezett végpontok és hivatkozás létrehozása
A végpontok nevet adhatnak a végpont URL-címeinek létrehozásához. A névvel ellátott végpontok használatával elkerülhető, hogy az alkalmazásokban ne kelljen kemény kódútvonalakat használni:
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();
Az előző kód megjeleníti a The link to the hello endpoint is /hello-t a / végpontról.
MEGJEGYZÉS: A végpontok neve megkülönbözteti a kis- és nagybetűket.
Végpontnevek:
- Globálisan egyedinek kell lennie.
- OpenAPI-műveletazonosítóként használatos, ha az OpenAPI-támogatás engedélyezve van. További információ: OpenAPI.
Útvonalparaméterek
Az útvonalparaméterek az útvonalminta definíciójának részeként rögzíthetők:
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();
Az előző kód a The user id is 3 and book id is 7 értéket adja vissza az URI /users/3/books/7-ből.
Az útvonalkezelő deklarálhatja a rögzítendő paramétereket. Amikor egy kérelem olyan útvonalat küld, amelynek a paraméterei rögzítésre vannak deklarálva, a rendszer elemzi és továbbítja a paramétereket a kezelőnek. Ez megkönnyíti az értékek biztonságos típusba rögzítését. Az előző kódban userId és bookId is int.
Az előző kódban, ha bármelyik útvonalértéket nem lehet int-é konvertálni, kivétel keletkezik. A GET kérés /users/hello/books/3 a következő kivételt okozza:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Helyettesítő karakter és az összes útvonal elfogása
A következő átfogó útvonal a "/posts/hello" végpontról Routing to hello-t ad vissza:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Útvonalkorlátozások
Az útvonalkorlátozások korlátozzák az útvonalak egyező viselkedését.
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();
Az alábbi táblázat az előző útvonalsablonokat és azok viselkedését mutatja be:
| Útvonalsablon | Példa egyező URI-ra |
|---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
További információért lásd: Útválasztási korlátozások hivatkozása a Útválasztás ASP.NET Corerészében.
Paraméterkötés
A paraméterkötés a kérelemadatok erősen gépelt paraméterekké alakításának folyamata, amelyeket az útvonalkezelők fejeznek ki. A kötési forrás határozza meg, hogy a paraméterek honnan vannak kötve. A kötési források lehetnek explicitek vagy következtethetők a HTTP-módszer és a paramétertípus alapján.
Támogatott kötési források:
- Útvonalértékek
- Lekérdezési karakterlánc
- Header
- Törzs (mint JSON)
- Függőséginjektálás által biztosított szolgáltatások
- Custom
Note
Az űrlapértékek kötése nem natív módon támogatott a .NET-ben.
A get útvonalkezelő az alábbi paraméterkötési források némelyikét használja:
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 { }
Az alábbi táblázat az előző példában használt paraméterek és a kapcsolódó kötési források közötti kapcsolatot mutatja be.
| Parameter | Kötés forrása |
|---|---|
id |
útvonal értéke |
page |
lekérdezési sztring |
customHeader |
fejléc |
service |
Függőséginjektálás által biztosított |
A HTTP-metódusok GET, HEAD, OPTIONSés DELETE nem kötődnek implicit módon a törzsből. A HTTP-metódusok törzséből (JSON-ként) való kötéshez kifejezetten[FromBody] vagy a HttpRequestolvasásához.
Az alábbi példában a POST útvonalkezelő egy kötési törzsforrást (JSON-ként) használ a person paraméterhez:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/", (Person person) => { });
record Person(string Name, int Age);
Az előző példákban szereplő paraméterek automatikusan kötődnek a kérelemadatokhoz. A paraméterkötés által biztosított kényelem bemutatásához az alábbi példaútmutatók bemutatják, hogyan olvashatók be közvetlenül a kérelem adatai a kérelemből:
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>();
// ...
});
Explicit paraméterkötés
Az attribútumokkal explicit módon deklarálható, hogy a paraméterek honnan vannak kötve.
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);
| Parameter | Kötés forrása |
|---|---|
id |
útvonalérték id |
page |
lekérdezési karakterlánc "p" nevű |
service |
Függőséginjektálás által biztosított |
contentType |
fejléc a "Content-Type" névvel |
Note
Az űrlapértékek kötése nem natív módon támogatott a .NET-ben.
Paraméterkötés DI-val
A minimális API-k paraméterkötése függőséginjektálási köti a paramétereket, ha a típus szolgáltatásként van konfigurálva. Nem szükséges explicit módon alkalmazni a [FromServices] attribútumot egy paraméterre. A következő kódban mindkét művelet az időt adja vissza:
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();
Választható paraméterek
Az útvonalkezelőkben deklarált paramétereket a rendszer szükség szerint kezeli:
- Ha egy kérelem megfelel az útvonalnak, az útvonalkezelő csak akkor fut, ha a kérelemben minden szükséges paraméter meg van adva.
- Ha nem adja meg az összes szükséges paramétert, az hibát eredményez.
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 visszaadott |
/products |
BadHttpRequestException: A szükséges "int pageNumber" paraméter nem lett megadva a lekérdezési sztringből. |
/products/1 |
HTTP 404-es hiba, nincs egyező útvonal |
Ha a pageNumber nem kötelezővé szeretné tenni, adja meg a típust opcionálisként, vagy adjon meg egy alapértelmezett értéket:
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 visszaadott |
/products |
1 visszaadott |
/products2 |
1 visszaadott |
Az előző null értékű és alapértelmezett érték az összes forrásra vonatkozik:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/products", (Product? product) => { });
app.Run();
Az előző kód null értékű termékkel hívja meg a metódust, ha nem küldenek kéréstörzset.
MEGJEGYZÉS: Ha érvénytelen adatokat ad meg, és a paraméter nullázható, az útvonalkezelő nem kerül végrehajtásra.
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 visszaérkezett |
/products |
1 visszaérkezett |
/products?pageNumber=two |
BadHttpRequestException: Nem sikerült megkötni a "Nullable<int> pageNumber" paramétert a "kettő" értékből. |
/products/two |
HTTP 404-es hiba, nincs egyező útvonal |
További információt a kötési hibák szakaszban talál.
Speciális típusok
A következő típusok explicit attribútumok nélkül vannak megkötve:
HttpContext: Az aktuális HTTP-kéréssel vagy -válaszsal kapcsolatos összes információt tartalmazó környezet:
app.MapGet("/", (HttpContext context) => context.Response.WriteAsync("Hello World"));HttpRequest és HttpResponse: A HTTP-kérés és a HTTP-válasz:
app.MapGet("/", (HttpRequest request, HttpResponse response) => response.WriteAsync($"Hello World {request.Query["name"]}"));CancellationToken: Az aktuális HTTP-kéréshez társított törlési token:
app.MapGet("/", async (CancellationToken cancellationToken) => await MakeLongRunningRequestAsync(cancellationToken));ClaimsPrincipal: A kérelemhez társított felhasználó, HttpContext.User:
app.MapGet("/", (ClaimsPrincipal user) => user.Identity.Name);
Egyéni kötés
A paraméterek kötését kétféleképpen szabhatjuk testre.
- Az útvonal-, lekérdezés- és fejléckötési forrásokhoz az egyéni típusok kötéséhez adjon hozzá egy statikus
TryParsemetódust a típushoz. - A kötési folyamat szabályozása egy
BindAsyncmetódus típuson való implementálásával.
TryParse
TryParse két API-val rendelkezik:
public static bool TryParse(string value, out T result);
public static bool TryParse(string value, IFormatProvider provider, out T result);
Az alábbi kód a Point: 12.3, 10.1 kódot jeleníti meg az URI /map?Point=12.3,10.1-el.
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 következő API-kkal rendelkezik:
public static ValueTask<T?> BindAsync(HttpContext context, ParameterInfo parameter);
public static ValueTask<T?> BindAsync(HttpContext context);
Az alábbi kód a SortBy:xyz, SortDirection:Desc, CurrentPage:99 kódot jeleníti meg az URI /products?SortBy=xyz&SortDir=Desc&Page=99-el.
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
}
Kötési hibák
Ha a kötés sikertelen, a keretrendszer hibakeresési üzenetet naplóz, és a hibamódtól függően különböző állapotkódokat ad vissza az ügyfélnek.
| Hiba mód | Null értékű paraméter típusa | Kötés forrása | Állapotkód |
|---|---|---|---|
{ParameterType}.TryParse visszaad false |
yes | route/query/header | 400 |
{ParameterType}.BindAsync visszaad null |
yes | custom | 400 |
{ParameterType}.BindAsync dobások |
nem számít | custom | 500 |
| A JSON-törzs deszerializálásának sikertelensége | nem számít | body | 400 |
Helytelen tartalomtípus (nem application/json) |
nem számít | body | 415 |
Kötési elsőbbség
A kötési forrás paraméterből való meghatározásának szabályai:
- A paraméteren (From* attribútumokon) definiált explicit attribútum a következő sorrendben:
- Útvonalértékek:
[FromRoute] - Lekérdezési karakterlánc:
[FromQuery] - Fejléc:
[FromHeader] - Törzs:
[FromBody] - Szolgáltatás:
[FromServices]
- Útvonalértékek:
- Speciális típusok
- A paramétertípus érvényes
BindAsyncmetódussal rendelkezik. - A paramétertípus egy sztring, vagy érvényes
TryParsemetódussal rendelkezik.- Ha a paraméter neve megtalálható az útvonalsablonban. A
app.Map("/todo/{id}", (int id) => {});idaz útvonalhoz van kötve. - Lekérdezési karakterláncból kötve.
- Ha a paraméter neve megtalálható az útvonalsablonban. A
- Ha a paramétertípus egy függőséginjektálás által biztosított szolgáltatás, akkor ezt a szolgáltatást használja forrásként.
- A paraméter a törzsből származik.
JSON-kötés testreszabása
A testkötési forrás a System.Text.Json-t használja deszerializáláshoz. Ezt az alapértelmezett beállítást nem lehet módosítani, de a kötés testre szabható a korábban ismertetett más technikákkal. A JSON szerializáló beállításainak testreszabásához használja a következőhöz hasonló kódot:
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;
}
Az előző kód:
- A bemeneti és kimeneti alapértelmezett JSON-beállításokat is konfigurálja.
- A következő JSON-t adja vissza
Közzétételkor{ "id": 1, "name": "Joe Smith" }{ "Id": 1, "Name": "Joe Smith" }
Olvassa el a kérés törzsét
Olvassa el a kérelem törzsét közvetlenül egy HttpContext vagy HttpRequest paraméter használatával:
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();
Az előző kód:
- A kérelmi törzshöz a HttpRequest.BodyReaderhasználatával fér hozzá.
- Másolja a kérelem törzsét egy helyi fájlba.
Responses
Az útvonalkezelők a következő típusú visszatérési értékeket támogatják:
-
IResultalapú – Ez magában foglalja aTask<IResult>-et és aValueTask<IResult>-t -
string– Ebbe beletartozikTask<string>ésValueTask<string> -
T(Bármilyen más típus) – Ebbe beletartozikTask<T>ésValueTask<T>
| Visszaadott érték | Behavior | Content-Type |
|---|---|---|
IResult |
A keretrendszer meghívja IResult.ExecuteAsync | A döntést a IResult végrehajtása hozta meg. |
string |
A keretrendszer közvetlenül a válaszba írja a sztringet | text/plain |
T (bármilyen más típus) |
A keretrendszer JSON szerializálja a választ | application/json |
Példa visszaadott értékekre
karakterlánc visszaadott értékei
app.MapGet("/hello", () => "Hello World");
JSON visszaadott értékek
app.MapGet("/hello", () => new { Message = "Hello World" });
IResult visszatérési értékek
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Az alábbi példa a beépített eredménytípusokat használja a válasz testreszabásához:
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" }));
Egyéni állapotkód
app.MapGet("/405", () => Results.StatusCode(405));
Text
app.MapGet("/text", () => Results.Text("This is some text"));
Stream
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();
Redirect
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
File
app.MapGet("/download", () => Results.File("myfile.text"));
Beépített eredmények
A gyakori eredménysegítők a Microsoft.AspNetCore.Http.Results statikus osztályban találhatók.
| Description | Válasz típusa | Állapotkód | API |
|---|---|---|---|
| JSON-válasz írása speciális beállításokkal | application/json | 200 | Results.Json |
| JSON-válasz írása | application/json | 200 | Results.Ok |
| Szöveges válasz írása | text/plain (alapértelmezett), konfigurálható | 200 | Results.Text |
| A választ bájtként írja ki | application/octet-stream (alapértelmezett), konfigurálható | 200 | Results.Bytes |
| Bájtokat tartalmazó adatfolyam írása a válaszba | application/octet-stream (alapértelmezett), konfigurálható | 200 | Results.Stream |
| Fájl streamelése a válaszba letöltésre a tartalomeloszlás fejlécével | application/octet-stream (alapértelmezett), konfigurálható | 200 | Results.File |
| Állítsa az állapotkódot 404-re, opcionális JSON-válaszsal | N/A | 404 | Results.NotFound |
| Az állapotkód beállítása 204-re | N/A | 204 | Results.NoContent |
| Állítsa az állapotkódot 422-re, opcionális JSON-válaszsal | N/A | 422 | Results.UnprocessableEntity |
| Az állapotkód beállítása 400-ra opcionális JSON-válaszsal | N/A | 400 | Results.BadRequest |
| Állítsa az állapotkódot 409-re, opcionális JSON-válaszsal | N/A | 409 | Results.Conflict |
| Probléma részleteinek megírása JSON-objektum a válaszhoz | N/A | 500 (alapértelmezett), konfigurálható | Results.Problem |
| Hiba részleteinek megírása JSON-objektummal a válaszhoz érvényesítési hibákkal | N/A | N/A, konfigurálható | Results.ValidationProblem |
Eredmények testreszabása
Az alkalmazások egyéni IResult típus implementálásával szabályozhatják a válaszokat. Az alábbi kód egy PÉLDA EGY HTML-eredménytípusra:
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);
}
}
Javasoljuk, hogy adjon hozzá egy bővítménymetódust a Microsoft.AspNetCore.Http.IResultExtensions az egyéni eredmények felderíthetőbbé tétele érdekében.
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();
Authorization
Az útvonalak engedélyezési szabályzatokkal védhetők. Ezek deklarálhatók a [Authorize] attribútummal vagy a RequireAuthorization metódussal:
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();
Az előző kód így is írható RequireAuthorization:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Az alábbi minta a házirenden alapuló engedélyezés használatát mutatja be.
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();
Végpont elérésének engedélyezése hitelesítés nélküli felhasználók számára
A [AllowAnonymous] lehetővé teszi, hogy a hitelesítés nélküli felhasználók hozzáférjenek a végpontokhoz:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Az útvonalak CORS- engedélyezhetők CORS-szabályzatokkal. A CORS deklarálható a [EnableCors] attribútummal vagy a RequireCors metódussal. A következő minták engedélyezik a CORS-t:
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();
További információkért nézze meg: Kereszt-származási kérelmek engedélyezése (CORS) az ASP.NET Core