Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Note
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 10 tohoto článku.
Warning
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Tento dokument:
- Poskytuje stručný přehled pro minimální rozhraní API.
- Je určený pro zkušené vývojáře. Úvod najdete v tématu Kurz: Vytvoření minimálního rozhraní API s ASP.NET Core.
Minimální rozhraní API se skládají z:
WebApplication
Následující kód je generován šablonou ASP.NET Core:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Předchozí kód lze vytvořit prostřednictvím dotnet new web příkazového řádku nebo výběrem prázdné webové šablony v sadě Visual Studio.
Následující kód vytvoří WebApplication (app) bez explicitního vytvoření WebApplicationBuilder:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create inicializuje novou instanci WebApplication třídy s předkonfigurovanými výchozími nastaveními.
WebApplication automaticky přidá následující middleware v aplikacích s minimálním rozhraním API v závislosti na určitých podmínkách:
-
UseDeveloperExceptionPageje přidána jako první, pokud jeHostingEnvironment."Development" -
UseRoutingse přidá sekundu, pokud se kód uživatele ještě nevolalUseRoutinga pokud jsou nakonfigurované koncové body, napříkladapp.MapGet. -
UseEndpointsse přidá na konec kanálu middlewaru, pokud jsou nakonfigurované nějaké koncové body. -
UseAuthenticationse přidá okamžitě poUseRoutingtom, co uživatelský kód ještě nezavolalUseAuthenticationa pokudIAuthenticationSchemeProviderje možné ho zjistit v poskytovateli služeb.IAuthenticationSchemeProviderje přidána ve výchozím nastavení při použitíAddAuthenticationa služby jsou zjištěny pomocíIServiceProviderIsService. -
UseAuthorizationse přidá dál, pokud kód uživatele ještě nezavolalUseAuthorizationa pokudIAuthorizationHandlerProviderje možné ho zjistit v poskytovateli služeb.IAuthorizationHandlerProviderje přidána ve výchozím nastavení při použitíAddAuthorizationa služby jsou zjištěny pomocíIServiceProviderIsService. - Mezi uživatelem nakonfigurovaný middleware a koncové body se přidají mezi
UseRoutingaUseEndpoints.
Následující kód je v podstatě to, co automatický middleware přidaný do aplikace vytvoří:
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 => {});
V některých případech není výchozí konfigurace middlewaru pro aplikaci správná a vyžaduje úpravy. Například UseCors by mělo být volána před UseAuthentication a UseAuthorization. Aplikace musí volat UseAuthentication a UseAuthorization pokud UseCors se volá:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Pokud by se měl middleware spustit před výskytem párování tras, UseRouting měl by být volána a middleware by měl být umístěn před voláním UseRouting.
UseEndpoints v tomto případě se nevyžaduje, protože se automaticky přidá, jak je popsáno výše:
app.Use((context, next) =>
{
return next(context);
});
app.UseRouting();
// other middleware and endpoints
Při přidávání middlewaru terminálu:
- Middleware musí být přidán za
UseEndpoints. - Aplikace musí volat
UseRouting,UseEndpointsaby middleware terminálu mohl být umístěn ve správném umístění.
app.UseRouting();
app.MapGet("/", () => "hello world");
app.UseEndpoints(e => {});
app.Run(context =>
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
Middleware terminálu je middleware, který se spustí, pokud požadavek nezpracuje žádný koncový bod.
Práce s porty
Při vytvoření webové aplikace pomocí sady Visual Studio nebo dotnet newProperties/launchSettings.json se vytvoří soubor, který určuje porty, na které aplikace reaguje. V ukázkách nastavení portů, které následují, vrátí spuštění aplikace ze sady Visual Studio dialogové okno Unable to connect to web server 'AppName's chybou . Visual Studio vrátí chybu, protože očekává port zadaný v Properties/launchSettings.jsonaplikaci, ale aplikace používá port určený app.Run("http://localhost:3000"). Z příkazového řádku spusťte následující ukázky změn portů.
Následující části nastavují port, na který aplikace reaguje.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
V předchozím kódu aplikace reaguje na port 3000.
Více portů
V následujícím kódu aplikace reaguje na port 3000 a 4000.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
Nastavení portu z příkazového řádku
Následující příkaz způsobí, že aplikace reaguje na port 7777:
dotnet run --urls="https://localhost:7777"
Kestrel Pokud je koncový bod také nakonfigurovaný v appsettings.json souboru, appsettings.json použije se zadaná adresa URL. Další informace najdete v tématu Kestrel Konfigurace koncového bodu.
Čtení portu z prostředí
Následující kód načte port z prostředí:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
Upřednostňovaným způsobem nastavení portu z prostředí je použití ASPNETCORE_URLS proměnné prostředí, která je znázorněna v následující části.
Nastavení portů prostřednictvím proměnné prostředí ASPNETCORE_URLS
Proměnná ASPNETCORE_URLS prostředí je k dispozici pro nastavení portu:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS podporuje více adres URL:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
Naslouchání na všech rozhraních
Následující ukázky ukazují naslouchání na všech rozhraních.
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();
Naslouchání všem rozhraním pomocí ASPNETCORE_URLS
Předchozí ukázky můžou použít ASPNETCORE_URLS
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
Naslouchání všem rozhraním pomocí ASPNETCORE_HTTPS_PORTS
Předchozí ukázky mohou používat ASPNETCORE_HTTPS_PORTS a ASPNETCORE_HTTP_PORTS.
ASPNETCORE_HTTP_PORTS=3000;5005
ASPNETCORE_HTTPS_PORTS=5000
Další informace najdete v tématu Konfigurace koncových bodů pro webový server ASP.NET Core Kestrel .
Zadání HTTPS s vývojovým certifikátem
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Další informace o vývojovém certifikátu najdete v tématu Důvěryhodnost vývojového certifikátu ASP.NET Core HTTPS ve Windows a macOS.
Zadání HTTPS pomocí vlastního certifikátu
Následující části ukazují, jak zadat vlastní certifikát pomocí appsettings.json souboru a prostřednictvím konfigurace.
Zadání vlastního certifikátu pomocí appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Zadání vlastního certifikátu prostřednictvím konfigurace
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();
Použití rozhraní API pro certifikáty
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();
Čtení prostředí
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();
Další informace o používání prostředí najdete v tématu runtime prostředí ASP.NET Core.
Configuration
Následující kód čte z konfiguračního systému:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Config failed!";
app.MapGet("/", () => message);
app.Run();
Další informace najdete v tématu Konfigurace v ASP.NET Core
Logging
Následující kód zapíše zprávu do protokolu při spuštění aplikace:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
Další informace najdete v tématu Protokolování v .NET a ASP.NET Core
Přístup ke kontejneru injektáže závislostí (DI)
Následující kód ukazuje, jak získat služby z kontejneru DI během spouštění aplikace:
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();
Následující kód ukazuje, jak přistupovat ke klíčům z kontejneru DI pomocí atributu [FromKeyedServices] :
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.";
}
Další informace o DI naleznete v tématu Injektáž závislostí v ASP.NET Core.
WebApplicationBuilder
Tato část obsahuje vzorový kód používající WebApplicationBuilder.
Změna kořenového adresáře obsahu, názvu aplikace a prostředí
Následující kód nastaví kořen obsahu, název aplikace a prostředí:
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 inicializuje novou instanci třídy WebApplicationBuilder s předkonfigurovanými výchozími hodnotami.
Další informace najdete v tématu ASP.NET Základní základní přehled
Změna kořenového adresáře obsahu, názvu aplikace a prostředí pomocí proměnných prostředí nebo příkazového řádku
Následující tabulka ukazuje proměnnou prostředí a argument příkazového řádku použitý ke změně kořenového adresáře obsahu, názvu aplikace a prostředí:
| atribut | Proměnná prostředí | Argument příkazového řádku |
|---|---|---|
| Název aplikace | ASPNETCORE_APPLICATIONNAME | --applicationName |
| Název prostředí | ASPNETCORE_ENVIRONMENT | --environment |
| Kořenový adresář obsahu | ASPNETCORE_CONTENTROOT | --contentRoot |
Přidání zprostředkovatelů konfigurace
Následující ukázka přidá zprostředkovatele konfigurace INI:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Podrobné informace najdete v tématu Zprostředkovatelé konfigurace souborů v části Konfigurace v ASP.NET Core.
Konfigurace čtení
Ve výchozím nastavení WebApplicationBuilder konfigurace čtení z více zdrojů, včetně:
-
appSettings.jsonaappSettings.{environment}.json - Proměnné prostředí
- Příkazový řádek
Úplný seznam přečtených zdrojů konfigurace najdete v tématu Výchozí konfigurace v konfiguraci v ASP.NET Core.
Následující kód načte HelloKey z konfigurace a zobrazí hodnotu v koncovém / bodu. Pokud má konfigurační hodnota hodnotu null, je "Hello" přiřazeno k message:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
Čtení prostředí
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsDevelopment())
{
Console.WriteLine($"Running in development.");
}
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Přidání zprostředkovatelů protokolování
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();
Přidání služeb
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();
Přizpůsobení nástroje IHostBuilder
K existujícím metodám IHostBuilder rozšíření lze přistupovat pomocí vlastnosti Host:
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();
Přizpůsobení IWebHostBuilderu
Metody rozšíření lze IWebHostBuilder získat přístup pomocí WebApplicationBuilder.WebHost vlastnost.
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();
Změna webového kořenového adresáře
Ve výchozím nastavení je kořenový adresář webu relativní ke kořenovému wwwroot adresáři obsahu ve složce. Webový kořenový adresář je místo, kde middleware statického souboru hledá statické soubory. Kořenový adresář webu lze změnit pomocí WebHostOptionspříkazového řádku nebo pomocí UseWebRoot metody:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Kontejner injektáže vlastních závislostí (DI)
Následující příklad používá autofac:
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();
Přidání middlewaru
Jakýkoli existující middleware ASP.NET Core je možné nakonfigurovat na :WebApplication
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
Další informace najdete v tématu ASP.NET Core Middleware
Stránka výjimky pro vývojáře
WebApplication.CreateBuilder inicializuje novou instanci WebApplicationBuilder třídy s předkonfigurovanými výchozími nastaveními. Stránka výjimky vývojáře je povolená v předkonfigurovaných výchozích nastaveních. Když se ve vývojovém prostředí spustí následující kód, přejdete k / vykreslení popisné stránky, která zobrazí výjimku.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () =>
{
throw new InvalidOperationException("Oops, the '/' route has thrown an exception.");
});
app.Run();
Middleware ASP.NET Core
Následující tabulka uvádí některé z middlewarů, které se často používají s minimálními rozhraními API.
| Middleware | Description | API |
|---|---|---|
| Authentication | Poskytuje podporu ověřování. | UseAuthentication |
| Authorization | Poskytuje podporu autorizace. | UseAuthorization |
| CORS | Konfiguruje sdílení prostředků mezi zdroji (CORS). | UseCors |
| Obslužná rutina výjimky | Globálně zpracovává výjimky vyvolané kanálem middlewaru. | UseExceptionHandler |
| Přeposílané hlavičky | Předá přeposílané hlavičky do aktuálního požadavku. | UseForwardedHeaders |
| Přesměrování HTTPS | Přesměruje všechny požadavky HTTP na HTTPS. | UseHttpsRedirection |
| Zabezpečení striktního přenosu HTTP (HSTS) | Middleware pro vylepšení zabezpečení, který přidává speciální hlavičku odpovědi. | UseHsts |
| Protokolování požadavku | Poskytuje podporu protokolování požadavků a odpovědí HTTP. | UseHttpLogging |
| Časové limity požadavků | Poskytuje podporu pro konfiguraci časových limitů požadavků, globálního výchozího a koncového bodu. | UseRequestTimeouts |
| Protokolování požadavků W3C | Poskytuje podporu pro protokolování požadavků HTTP a odpovědí ve formátu W3C. | UseW3CLogging |
| Ukládání odpovědí do mezipaměti | Poskytuje podporu pro ukládání odpovědí do mezipaměti. | UseResponseCaching |
| Komprese odpovědí | Poskytuje podporu pro kompresi odpovědí. | UseResponseCompression |
| Session | Poskytuje podporu pro správu uživatelských relací. | UseSession |
| Statické soubory | Poskytuje podporu pro obsluhu statických souborů a procházení adresářů. | UseStaticFiles, UseFileServer |
| WebSockets | Povoluje protokol WebSocket. | UseWebSockets |
Následující části zahrnují zpracování požadavků: směrování, vazby parametrů a odpovědi.
Routing
Nakonfigurovaná podpora a kde je metoda HTTP typu camel cased, například WebApplication, Map{Verb}, MapMethodsnebo {Verb}:GetPostPutDelete
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();
Argumenty Delegate předané těmto metodám se nazývají "obslužné rutiny tras".
Obslužné rutiny tras
Obslužné rutiny tras jsou metody, které se spouštějí, když se trasa shoduje. Obslužné rutiny tras mohou být výraz lambda, místní funkce, metoda instance nebo statická metoda. Obslužné rutiny tras můžou být synchronní nebo asynchronní.
Výraz lambda
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();
Místní funkce
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Metoda instance
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";
}
}
Statická metoda
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";
}
}
Koncový bod definovaný mimo Program.cs
Minimální rozhraní API nemusí být umístěna v Program.csumístění .
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" });
});
}
}
Viz také skupiny Směrování dále v tomto článku.
Pojmenované koncové body a generování propojení
Koncové body můžou mít názvy, aby se vygenerovaly adresy URL koncového bodu. Použitím pojmenovaného koncového bodu se v aplikaci nemusíte pevně zakódovat cesty:
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();
Předchozí kód se zobrazí The link to the hello route is /hello z koncového / bodu.
POZNÁMKA: V názvech koncových bodů se rozlišují malá a velká písmena.
Názvy koncových bodů:
- Musí být globálně jedinečný.
- Používají se jako ID operace OpenAPI, pokud je povolená podpora OpenAPI. Další informace najdete v tématu OpenAPI.
Parametry trasy
Parametry trasy je možné zachytit jako součást definice vzoru trasy:
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();
Předchozí kód vrátí The user id is 3 and book id is 7 z identifikátoru URI /users/3/books/7.
Obslužná rutina trasy může deklarovat parametry, které se mají zachytit. Při provedení požadavku na trasu s parametry deklarovanými k zachycení se parametry parsují a předávají obslužné rutině. To usnadňuje zachytávání hodnot v bezpečném typu. V předchozím kódu userId a bookId jsou oba int.
Pokud v předchozím kódu nelze převést intna některou hodnotu trasy , vyvolá se výjimka. Požadavek /users/hello/books/3 GET vyvolá následující výjimku:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Zástupný znak a zachycení všech tras
Následující zachytávání všech návratových tras Routing to hello z koncového bodu /posts/hello:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Omezení trasy
Omezení trasy omezují odpovídající chování trasy.
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();
Následující tabulka ukazuje předchozí šablony tras a jejich chování:
| Šablona trasy | Příklad odpovídajícího identifikátoru URI |
|---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
Další informace najdete v tématu Referenční informace o omezení trasy ve směrování v ASP.NET Core.
Skupiny tras
Metoda MapGroup rozšíření pomáhá uspořádat skupiny koncových bodů s běžnou předponou. Snižuje opakující se kód a umožňuje přizpůsobit celé skupiny koncových bodů jediným voláním metod, jako RequireAuthorization jsou a WithMetadata které přidávají metadata koncového bodu.
Například následující kód vytvoří dvě podobné skupiny koncových bodů:
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;
}
V tomto scénáři můžete použít relativní adresu hlavičky Location ve výsledku 201 Created :
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
První skupina koncových bodů se bude shodovat pouze s požadavky s předponou /public/todos a jsou přístupná bez ověřování. Druhá skupina koncových bodů bude odpovídat pouze požadavkům s předponou /private/todos a vyžaduje ověření.
Objekt QueryPrivateTodospro filtrování koncových bodů je místní funkce, která upravuje parametry obslužné rutiny TodoDb trasy tak, aby umožňovala přístup k privátním datům úkolů a jejich ukládání.
Skupiny tras také podporují vnořené skupiny a složité vzory předpon s parametry trasy a omezeními. V následujícím příkladu a obslužná rutina trasy namapovaná na user skupinu může zachytit {org} parametry a {group} parametry trasy definované v předponách vnější skupiny.
Předpona může být také prázdná. To může být užitečné pro přidání metadat koncového bodu nebo filtrů do skupiny koncových bodů beze změny vzoru trasy.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
Přidání filtrů nebo metadat do skupiny se chová stejně jako jejich individuální přidání do každého koncového bodu před přidáním dalších filtrů nebo metadat, které mohly být přidány do vnitřní skupiny nebo konkrétního koncového bodu.
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);
});
V předchozím příkladu vnější filtr zapíše příchozí požadavek před vnitřním filtrem, i když byl přidán druhý. Vzhledem k tomu, že filtry byly použity u různých skupin, pořadí, které byly přidány vzhledem k sobě, nezáleží. Přidají se filtry objednávek bez ohledu na to, jestli se použije na stejnou skupinu nebo konkrétní koncový bod.
Žádost o /outer/inner/ protokolování bude následující:
/outer group filter
/inner group filter
MapGet filter
Vazba parametru
Vazba parametru je proces převodu dat požadavku na parametry silného typu, které jsou vyjádřeny obslužnými rutinami tras. Zdroj vazby určuje, odkud jsou parametry vázány. Zdroje vazeb můžou být explicitní nebo odvozené na základě metody HTTP a typu parametru.
Podporované zdroje vazeb:
- Hodnoty tras
- Řetězec dotazu
- Header
- Text (jako JSON)
- Hodnoty formuláře
- Služby poskytované injektáží závislostí
- Custom
Následující obslužná rutina trasy GET používá některé z těchto zdrojů vazeb parametrů:
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 { }
Funkce vazby klíčových parametrů
-
Explicitní vazba: Použijte atributy, jako jsou
[FromRoute],[FromQuery],[FromHeader],[FromBody],[FromForm]a[FromServices], k explicitnímu určení zdrojů vazeb. -
Vázání formuláře: Vytváření vazby hodnot formuláře pomocí
[FromForm]atributu, včetně podpory proIFormFileaIFormFileCollectionpro nahrávání souborů. - Komplexní typy: Vazba na kolekce a komplexní typy z formulářů, dotazovacích řetězců a hlaviček.
-
Vlastní vazba: Implementujte vlastní logiku vazby pomocí
TryParse,BindAsyncneboIBindableFromHttpContext<T>rozhraní. - Volitelné parametry: Podporují typy s možnou hodnotou null a výchozí hodnoty pro volitelné parametry.
- Injektáž závislostí: Parametry jsou automaticky vázány ze služeb registrovaných v kontejneru DI.
-
Speciální typy: Automatické vazby pro
HttpContext,HttpRequest,HttpResponse,CancellationToken,ClaimsPrincipal, , ,Stream, aPipeReader.
Víc se uč: Podrobné informace o vazbě parametrů, včetně pokročilých scénářů, ověření, priority vazeb a řešení potíží, najdete v tématu Vazby parametrů v aplikacích s minimálním rozhraním API.
Deserializace Json+PipeReader v minimálních rozhraních API
Počínaje platformou .NET 10 používají následující funkční oblasti ASP.NET Core přetížení JsonSerializer.DeserializeAsync založená na PipeReader místo streamu:
- Minimální rozhraní API (vazby parametrů, text požadavku pro čtení)
- MVC (vstupní formátovací moduly, model)
- Metody HttpRequestJsonExtensions rozšíření pro čtení těla požadavku ve formátu JSON.
U většiny aplikací poskytuje přechod ze Streamu na PipeReader lepší výkon bez nutnosti změn v kódu aplikace. Pokud ale vaše aplikace obsahuje vlastní převaděč, převaděč nemusí správně zpracovat Utf8JsonReader.HasValueSequence . Pokud ne, může dojít k chybám, jako je ArgumentOutOfRangeException nebo chybějící data při deserializaci. Pro práci převaděče bez chyb souvisejících s PipeReader máte následující možnosti.
Možnost 1: Dočasné alternativní řešení
Rychlým alternativním řešením je vrátit se k používání Streamu bez podpory PipeReader. Pokud chcete tuto možnost implementovat, nastavte přepínač AppContext Microsoft.AspNetCore.UseStreamBasedJsonParsing na hodnotu true. Doporučujeme, abyste to udělali jenom jako dočasné alternativní řešení a co nejdříve ho aktualizujte tak, aby podporoval podporu HasValueSequence . Přepínač může být odebrán v .NET 11. Jeho jediným účelem bylo poskytnout vývojářům čas na aktualizaci jejich převaděčů.
Možnost 2: Rychlá oprava pro JsonConverter implementace
Pro tuto opravu přidělíte pole z objektu ReadOnlySequence. Tento příklad ukazuje, jak by kód vypadal:
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
// previous code
}
Možnost 3: Složitější, ale lépe fungující oprava
Tato oprava zahrnuje nastavení samostatné cesty kódu pro ReadOnlySequence zpracování:
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
}
}
Další informace viz
Podpora ověřování v minimálních rozhraních API
Povolení ověřování umožňuje modulu runtime ASP.NET Core provádět ověření definovaná na:
- Query
- Header
- Obsah požadavku
Ověření jsou definována pomocí atributů v DataAnnotations oboru názvů.
Pokud je parametr minimálního koncového bodu rozhraní API třída nebo typ záznamu, automaticky se použijí ověřovací atributy. Například:
public record Product(
[Required] string Name,
[Range(1, 1000)] int Quantity);
Vývojáři přizpůsobují chování ověřovacího systému pomocí následujících možností:
- Vytváření vlastních
[Validation]implementací atributů - Implementace rozhraní
IValidatableObjectpro komplexní ověřovací logiku.
Pokud se ověření nezdaří, modul runtime vrátí odpověď 400 – Chybný požadavek s podrobnostmi o chybách ověření.
Povolení integrované podpory ověřování pro minimální rozhraní API
Povolte integrovanou podporu ověřování pro minimální rozhraní API voláním AddValidation metody rozšíření pro registraci požadovaných služeb v kontejneru služby pro vaši aplikaci:
builder.Services.AddValidation();
Implementace automaticky zjišťuje typy definované v obslužných rutinách minimálního rozhraní API nebo jako základní typy typů definovaných v obslužných rutinách minimálního rozhraní API. Filtr koncového bodu provádí ověření u těchto typů a přidá se pro každý koncový bod.
Ověření je možné zakázat pro konkrétní koncové body pomocí DisableValidation metody rozšíření, jak je znázorněno v následujícím příkladu:
app.MapPost("/products",
([EvenNumber(ErrorMessage = "Product ID must be even")] int productId, [Required] string name)
=> TypedResults.Ok(productId))
.DisableValidation();
Přizpůsobení odpovědí na chyby ověřování pomocí IProblemDetailsService
Přizpůsobte odpovědi na chyby z logiky minimálního IProblemDetailsService ověření rozhraní API pomocí implementace. Zaregistrujte tuto službu v kolekci služeb vaší aplikace, abyste povolili konzistentnější odpovědi na chyby specifické pro uživatele. Podpora minimálního ověřování rozhraní API byla zavedena v ASP.NET Core v .NET 10.
Implementace vlastních odpovědí na chyby ověřování:
- Implementace IProblemDetailsService nebo použití výchozí implementace
- Registrace služby v kontejneru DI
- Ověřovací systém automaticky používá zaregistrovanou službu k formátování odpovědí na chyby ověřování.
Další informace o přizpůsobení odpovědí na chyby ověřování pomocí IProblemDetailsService najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Responses
Obslužné rutiny tras podporují následující typy návratových hodnot:
-
IResultna základě – to zahrnujeTask<IResult>aValueTask<IResult> -
string- To zahrnujeTask<string>aValueTask<string> -
T(Jakýkoli jiný typ) – to zahrnujeTask<T>aValueTask<T>
| Návratová hodnota | Behavior | Content-Type |
|---|---|---|
IResult |
Architektura volá IResult.ExecuteAsync. | Rozhodlo se implementací IResult |
string |
Architektura zapíše řetězec přímo do odpovědi. | text/plain |
T (Jakýkoli jiný typ) |
Rozhraní JSON serializuje odpověď. | application/json |
Podrobnější průvodce směrováním vrácených hodnot obslužné rutiny najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Příklad návratových hodnot
řetězcové návratové hodnoty
app.MapGet("/hello", () => "Hello World");
Návratové hodnoty JSON
app.MapGet("/hello", () => new { Message = "Hello World" });
Vrácení TypedResults
Následující kód vrátí TypedResults:
app.MapGet("/hello", () => TypedResults.Ok(new Message() { Text = "Hello World!" }));
TypedResults Vrácení je upřednostňované pro vrácení Results. Další informace naleznete v tématu TypedResults vs Výsledky.
Návratové hodnoty IResult
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Následující příklad používá předdefinované typy výsledků k přizpůsobení odpovědi:
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" }));
Vlastní stavový kó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");
});
Další příklady najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Redirect
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
File
app.MapGet("/download", () => Results.File("myfile.text"));
Předdefinované výsledky
Běžné pomocné rutiny výsledků existují ve statických ResultsTypedResults třídách.
TypedResults Vrácení je upřednostňované pro vrácení Results. Další informace naleznete v tématu TypedResults vs Výsledky.
Úprava hlaviček
Pomocí objektu HttpResponse upravte hlavičky odpovědi:
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";
});
Přizpůsobení výsledků
Aplikace můžou řídit odpovědi implementací vlastního IResult typu. Následující kód je příkladem typu výsledku HTML:
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);
}
}
Doporučujeme přidat metodu rozšíření, aby Microsoft.AspNetCore.Http.IResultExtensions byly tyto vlastní výsledky lépe zjistitelné.
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();
Zadané výsledky
Rozhraní IResult může představovat hodnoty vrácené z minimálních rozhraní API, které nevyužívají implicitní podporu pro serializaci vráceného objektu do odpovědi HTTP.
Static Results třída slouží k vytvoření různých IResult objektů, které představují různé typy odpovědí. Můžete například nastavit stavový kód odpovědi nebo přesměrovat na jinou adresu URL.
Implementované IResult typy jsou veřejné, což umožňuje při testování kontrolní výrazy typů. Například:
[TestClass()]
public class WeatherApiTests
{
[TestMethod()]
public void MapWeatherApiTest()
{
var result = WeatherApi.GetAllWeathers();
Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
}
}
Můžete se podívat na návratové typy odpovídajících metod ve statické TypedResults třídy najít správný veřejný IResult typ, na který se má přetypovat.
Další příklady najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Filters
Další informace najdete v tématu Filtry v minimálních aplikacích API.
Authorization
Trasy je možné chránit pomocí zásad autorizace. Tyto můžou být deklarovány prostřednictvím atributu [Authorize] nebo pomocí RequireAuthorization metody:
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();
Předchozí kód lze napsat takto RequireAuthorization:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Následující ukázka používá autorizaci založenou na zásadách:
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();
Povolit neověřeným uživatelům přístup ke koncovému bodu
Umožňuje [AllowAnonymous] neověřeným uživatelům přístup ke koncovým bodům:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Trasy můžou být povolené CORS pomocí zásad CORS. CORS lze deklarovat prostřednictvím atributu [EnableCors] nebo pomocí RequireCors metody. Následující ukázky umožňují 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("/",() => "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();
Další informace najdete v tématu Povolení žádostí mezi zdroji (CORS) v ASP.NET Core
ValidateScopes a ValidateOnBuild
ValidateScopesa ValidateOnBuild jsou ve výchozím nastavení povolené ve vývojovém prostředí, ale jsou zakázané v jiných prostředích.
Pokud ValidateOnBuild je , truekontejner DI ověří konfiguraci služby v době sestavení. Pokud je konfigurace služby neplatná, sestavení selže při spuštění aplikace, a ne za běhu při vyžádání služby.
V ValidateScopes takovém případě truekontejner DI ověří, že služba s vymezeným oborem není přeložena z kořenového oboru. Překlad služby s vymezeným oborem z kořenového oboru může vést k nevracení paměti, protože služba je zachována v paměti delší než rozsah požadavku.
ValidateScopes a ValidateOnBuild jsou ve výchozím nastavení nepravdivé v režimech mimo vývoj z důvodů výkonu.
Následující kód je ValidateScopes ve výchozím nastavení povolený ve vývojovém režimu, ale v režimu vydání je zakázaný:
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 { }
Následující kód je ValidateOnBuild ve výchozím nastavení povolený ve vývojovém režimu, ale v režimu vydání je zakázaný:
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 { }
Následující kód zakáže ValidateScopes a ValidateOnBuild v Development:
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;
});
}
Viz také
- Stručná referenční dokumentace k minimálním rozhraním API
- Generování dokumentů OpenAPI
- Vytváření odpovědí v aplikacích s minimálním rozhraním API
- Filtry v minimálních aplikacích API
- Zpracování chyb v rozhraních API ASP.NET Core
- Ověřování a autorizace v minimálních rozhraních API
- Testování minimálních aplikací API
- Směrování zkratek
- Identity Koncové body rozhraní API
- Podpora kontejneru injektáže závislostí služby s klíči
- Pohled na pozadí minimálních koncových bodů rozhraní API
- Uspořádání ASP.NET základních minimálních rozhraní API
- Diskuze o ověřování fluentu na GitHubu
Tento dokument:
- Poskytuje stručný přehled minimálních rozhraní API.
- Je určený pro zkušené vývojáře. Úvod najdete v tématu Kurz: Vytvoření minimálního rozhraní API s ASP.NET Core.
Minimální rozhraní API se skládají z:
WebApplication
Následující kód je generován šablonou ASP.NET Core:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Předchozí kód lze vytvořit prostřednictvím dotnet new web příkazového řádku nebo výběrem prázdné webové šablony v sadě Visual Studio.
Následující kód vytvoří WebApplication (app) bez explicitního vytvoření WebApplicationBuilder:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create inicializuje novou instanci WebApplication třídy s předkonfigurovanými výchozími nastaveními.
WebApplication automaticky přidá následující middleware v aplikacích s minimálním rozhraním API v závislosti na určitých podmínkách:
-
UseDeveloperExceptionPageje přidána jako první, pokud jeHostingEnvironment."Development" -
UseRoutingse přidá sekundu, pokud se kód uživatele ještě nevolalUseRoutinga pokud jsou nakonfigurované koncové body, napříkladapp.MapGet. -
UseEndpointsse přidá na konec kanálu middlewaru, pokud jsou nakonfigurované nějaké koncové body. -
UseAuthenticationse přidá okamžitě poUseRoutingtom, co uživatelský kód ještě nezavolalUseAuthenticationa pokudIAuthenticationSchemeProviderje možné ho zjistit v poskytovateli služeb.IAuthenticationSchemeProviderje přidána ve výchozím nastavení při použitíAddAuthenticationa služby jsou zjištěny pomocíIServiceProviderIsService. -
UseAuthorizationse přidá dál, pokud kód uživatele ještě nezavolalUseAuthorizationa pokudIAuthorizationHandlerProviderje možné ho zjistit v poskytovateli služeb.IAuthorizationHandlerProviderje přidána ve výchozím nastavení při použitíAddAuthorizationa služby jsou zjištěny pomocíIServiceProviderIsService. - Mezi uživatelem nakonfigurovaný middleware a koncové body se přidají mezi
UseRoutingaUseEndpoints.
Následující kód je v podstatě to, co automatický middleware přidaný do aplikace vytvoří:
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 => {});
V některých případech není výchozí konfigurace middlewaru pro aplikaci správná a vyžaduje úpravy. Například UseCors by mělo být volána před UseAuthentication a UseAuthorization. Aplikace musí volat UseAuthentication a UseAuthorization pokud UseCors se volá:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Pokud by se měl middleware spustit před výskytem párování tras, UseRouting měl by být volána a middleware by měl být umístěn před voláním UseRouting.
UseEndpoints v tomto případě se nevyžaduje, protože se automaticky přidá, jak je popsáno výše:
app.Use((context, next) =>
{
return next(context);
});
app.UseRouting();
// other middleware and endpoints
Při přidávání middlewaru terminálu:
- Middleware musí být přidán za
UseEndpoints. - Aplikace musí volat
UseRouting,UseEndpointsaby middleware terminálu mohl být umístěn ve správném umístění.
app.UseRouting();
app.MapGet("/", () => "hello world");
app.UseEndpoints(e => {});
app.Run(context =>
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
Middleware terminálu je middleware, který se spustí, pokud požadavek nezpracuje žádný koncový bod.
Práce s porty
Při vytvoření webové aplikace pomocí sady Visual Studio nebo dotnet newProperties/launchSettings.json se vytvoří soubor, který určuje porty, na které aplikace reaguje. V ukázkách nastavení portů, které následují, vrátí spuštění aplikace ze sady Visual Studio dialogové okno Unable to connect to web server 'AppName's chybou . Visual Studio vrátí chybu, protože očekává port zadaný v Properties/launchSettings.jsonaplikaci, ale aplikace používá port určený app.Run("http://localhost:3000"). Z příkazového řádku spusťte následující ukázky změn portů.
Následující části nastavují port, na který aplikace reaguje.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
V předchozím kódu aplikace reaguje na port 3000.
Více portů
V následujícím kódu aplikace reaguje na port 3000 a 4000.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
Nastavení portu z příkazového řádku
Následující příkaz způsobí, že aplikace reaguje na port 7777:
dotnet run --urls="https://localhost:7777"
Kestrel Pokud je koncový bod také nakonfigurovaný v appsettings.json souboru, appsettings.json použije se zadaná adresa URL. Další informace najdete v tématu Kestrel Konfigurace koncového bodu.
Čtení portu z prostředí
Následující kód načte port z prostředí:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
Upřednostňovaným způsobem nastavení portu z prostředí je použití ASPNETCORE_URLS proměnné prostředí, která je znázorněna v následující části.
Nastavení portů prostřednictvím proměnné prostředí ASPNETCORE_URLS
Proměnná ASPNETCORE_URLS prostředí je k dispozici pro nastavení portu:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS podporuje více adres URL:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
Naslouchání na všech rozhraních
Následující ukázky ukazují naslouchání na všech rozhraních.
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();
Naslouchání všem rozhraním pomocí ASPNETCORE_URLS
Předchozí ukázky můžou použít ASPNETCORE_URLS
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
Naslouchání všem rozhraním pomocí ASPNETCORE_HTTPS_PORTS
Předchozí ukázky mohou používat ASPNETCORE_HTTPS_PORTS a ASPNETCORE_HTTP_PORTS.
ASPNETCORE_HTTP_PORTS=3000;5005
ASPNETCORE_HTTPS_PORTS=5000
Další informace najdete v tématu Konfigurace koncových bodů pro webový server ASP.NET Core Kestrel .
Zadání HTTPS s vývojovým certifikátem
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Další informace o vývojovém certifikátu najdete v tématu Důvěryhodnost vývojového certifikátu ASP.NET Core HTTPS ve Windows a macOS.
Zadání HTTPS pomocí vlastního certifikátu
Následující části ukazují, jak zadat vlastní certifikát pomocí appsettings.json souboru a prostřednictvím konfigurace.
Zadání vlastního certifikátu pomocí appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Zadání vlastního certifikátu prostřednictvím konfigurace
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();
Použití rozhraní API pro certifikáty
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();
Čtení prostředí
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();
Další informace o používání prostředí najdete v tématu runtime prostředí ASP.NET Core.
Configuration
Následující kód čte z konfiguračního systému:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Config failed!";
app.MapGet("/", () => message);
app.Run();
Další informace najdete v tématu Konfigurace v ASP.NET Core
Logging
Následující kód zapíše zprávu do protokolu při spuštění aplikace:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
Další informace najdete v tématu Protokolování v .NET a ASP.NET Core
Přístup ke kontejneru injektáže závislostí (DI)
Následující kód ukazuje, jak získat služby z kontejneru DI během spouštění aplikace:
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();
Následující kód ukazuje, jak přistupovat ke klíčům z kontejneru DI pomocí atributu [FromKeyedServices] :
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.";
}
Další informace o DI naleznete v tématu Injektáž závislostí v ASP.NET Core.
WebApplicationBuilder
Tato část obsahuje vzorový kód používající WebApplicationBuilder.
Změna kořenového adresáře obsahu, názvu aplikace a prostředí
Následující kód nastaví kořen obsahu, název aplikace a prostředí:
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 inicializuje novou instanci třídy WebApplicationBuilder s předkonfigurovanými výchozími hodnotami.
Další informace najdete v tématu ASP.NET Základní základní přehled
Změna kořenového adresáře obsahu, názvu aplikace a prostředí pomocí proměnných prostředí nebo příkazového řádku
Následující tabulka ukazuje proměnnou prostředí a argument příkazového řádku použitý ke změně kořenového adresáře obsahu, názvu aplikace a prostředí:
| atribut | Proměnná prostředí | Argument příkazového řádku |
|---|---|---|
| Název aplikace | ASPNETCORE_APPLICATIONNAME | --applicationName |
| Název prostředí | ASPNETCORE_ENVIRONMENT | --environment |
| Kořenový adresář obsahu | ASPNETCORE_CONTENTROOT | --contentRoot |
Přidání zprostředkovatelů konfigurace
Následující ukázka přidá zprostředkovatele konfigurace INI:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Podrobné informace najdete v tématu Zprostředkovatelé konfigurace souborů v části Konfigurace v ASP.NET Core.
Konfigurace čtení
Ve výchozím nastavení WebApplicationBuilder konfigurace čtení z více zdrojů, včetně:
-
appSettings.jsonaappSettings.{environment}.json - Proměnné prostředí
- Příkazový řádek
Úplný seznam přečtených zdrojů konfigurace najdete v tématu Výchozí konfigurace v konfiguraci v ASP.NET Core.
Následující kód načte HelloKey z konfigurace a zobrazí hodnotu v koncovém / bodu. Pokud má konfigurační hodnota hodnotu null, je "Hello" přiřazeno k message:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
Čtení prostředí
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsDevelopment())
{
Console.WriteLine($"Running in development.");
}
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Přidání zprostředkovatelů protokolování
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();
Přidání služeb
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();
Přizpůsobení nástroje IHostBuilder
K existujícím metodám IHostBuilder rozšíření lze přistupovat pomocí vlastnosti Host:
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();
Přizpůsobení IWebHostBuilderu
Metody rozšíření lze IWebHostBuilder získat přístup pomocí WebApplicationBuilder.WebHost vlastnost.
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();
Změna webového kořenového adresáře
Ve výchozím nastavení je kořenový adresář webu relativní ke kořenovému wwwroot adresáři obsahu ve složce. Webový kořenový adresář je místo, kde middleware statického souboru hledá statické soubory. Kořenový adresář webu lze změnit pomocí WebHostOptionspříkazového řádku nebo pomocí UseWebRoot metody:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Kontejner injektáže vlastních závislostí (DI)
Následující příklad používá autofac:
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();
Přidání middlewaru
Jakýkoli existující middleware ASP.NET Core je možné nakonfigurovat na :WebApplication
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
Další informace najdete v tématu ASP.NET Core Middleware
Stránka výjimky pro vývojáře
WebApplication.CreateBuilder inicializuje novou instanci WebApplicationBuilder třídy s předkonfigurovanými výchozími nastaveními. Stránka výjimky vývojáře je povolená v předkonfigurovaných výchozích nastaveních. Když se ve vývojovém prostředí spustí následující kód, přejdete k / vykreslení popisné stránky, která zobrazí výjimku.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () =>
{
throw new InvalidOperationException("Oops, the '/' route has thrown an exception.");
});
app.Run();
Middleware ASP.NET Core
Následující tabulka uvádí některé z middlewarů, které se často používají s minimálními rozhraními API.
| Middleware | Description | API |
|---|---|---|
| Authentication | Poskytuje podporu ověřování. | UseAuthentication |
| Authorization | Poskytuje podporu autorizace. | UseAuthorization |
| CORS | Konfiguruje sdílení prostředků mezi zdroji (CORS). | UseCors |
| Obslužná rutina výjimky | Globálně zpracovává výjimky vyvolané kanálem middlewaru. | UseExceptionHandler |
| Přeposílané hlavičky | Předá přeposílané hlavičky do aktuálního požadavku. | UseForwardedHeaders |
| Přesměrování HTTPS | Přesměruje všechny požadavky HTTP na HTTPS. | UseHttpsRedirection |
| Zabezpečení striktního přenosu HTTP (HSTS) | Middleware pro vylepšení zabezpečení, který přidává speciální hlavičku odpovědi. | UseHsts |
| Protokolování požadavku | Poskytuje podporu protokolování požadavků a odpovědí HTTP. | UseHttpLogging |
| Časové limity požadavků | Poskytuje podporu pro konfiguraci časových limitů požadavků, globálního výchozího a koncového bodu. | UseRequestTimeouts |
| Protokolování požadavků W3C | Poskytuje podporu pro protokolování požadavků HTTP a odpovědí ve formátu W3C. | UseW3CLogging |
| Ukládání odpovědí do mezipaměti | Poskytuje podporu pro ukládání odpovědí do mezipaměti. | UseResponseCaching |
| Komprese odpovědí | Poskytuje podporu pro kompresi odpovědí. | UseResponseCompression |
| Session | Poskytuje podporu pro správu uživatelských relací. | UseSession |
| Statické soubory | Poskytuje podporu pro obsluhu statických souborů a procházení adresářů. | UseStaticFiles, UseFileServer |
| WebSockets | Povoluje protokol WebSocket. | UseWebSockets |
Následující části zahrnují zpracování požadavků: směrování, vazby parametrů a odpovědi.
Routing
Nakonfigurovaná podpora a kde je metoda HTTP typu camel-cased, například WebApplication, Map{Verb}nebo MapMethods{Verb}:GetPostPutDelete
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();
Argumenty Delegate předané těmto metodám se nazývají "obslužné rutiny tras".
Obslužné rutiny tras
Obslužné rutiny tras jsou metody, které se spouštějí, když se trasa shoduje. Obslužné rutiny tras mohou být výraz lambda, místní funkce, metoda instance nebo statická metoda. Obslužné rutiny tras můžou být synchronní nebo asynchronní.
Výraz lambda
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();
Místní funkce
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Metoda instance
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";
}
}
Statická metoda
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";
}
}
Koncový bod definovaný mimo Program.cs
Minimální rozhraní API nemusí být umístěna v Program.csumístění .
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" });
});
}
}
Viz také skupiny Směrování dále v tomto článku.
Pojmenované koncové body a generování propojení
Koncové body můžou mít názvy, aby se vygenerovaly adresy URL koncového bodu. Použitím pojmenovaného koncového bodu se v aplikaci nemusíte pevně zakódovat cesty:
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();
Předchozí kód se zobrazí The link to the hello route is /hello z koncového / bodu.
POZNÁMKA: V názvech koncových bodů se rozlišují malá a velká písmena.
Názvy koncových bodů:
- Musí být globálně jedinečný.
- Používají se jako ID operace OpenAPI, pokud je povolená podpora OpenAPI. Další informace najdete v tématu OpenAPI.
Parametry trasy
Parametry trasy je možné zachytit jako součást definice vzoru trasy:
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();
Předchozí kód vrátí The user id is 3 and book id is 7 z identifikátoru URI /users/3/books/7.
Obslužná rutina trasy může deklarovat parametry, které se mají zachytit. Při provedení požadavku na trasu s parametry deklarovanými k zachycení se parametry parsují a předávají obslužné rutině. To usnadňuje zachytávání hodnot v bezpečném typu. V předchozím kódu userId a bookId jsou oba int.
Pokud v předchozím kódu nelze převést intna některou hodnotu trasy , vyvolá se výjimka. Požadavek /users/hello/books/3 GET vyvolá následující výjimku:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Zástupný znak a zachycení všech tras
Následující zachytávání všech návratových tras Routing to hello z koncového bodu /posts/hello:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Omezení trasy
Omezení trasy omezují odpovídající chování trasy.
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();
Následující tabulka ukazuje předchozí šablony tras a jejich chování:
| Šablona trasy | Příklad odpovídajícího identifikátoru URI |
|---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
Další informace najdete v tématu Referenční informace o omezení trasy ve směrování v ASP.NET Core.
Skupiny tras
Metoda MapGroup rozšíření pomáhá uspořádat skupiny koncových bodů s běžnou předponou. Snižuje opakující se kód a umožňuje přizpůsobit celé skupiny koncových bodů jediným voláním metod, jako RequireAuthorization jsou a WithMetadata které přidávají metadata koncového bodu.
Například následující kód vytvoří dvě podobné skupiny koncových bodů:
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;
}
V tomto scénáři můžete použít relativní adresu hlavičky Location ve výsledku 201 Created :
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
První skupina koncových bodů se bude shodovat pouze s požadavky s předponou /public/todos a jsou přístupná bez ověřování. Druhá skupina koncových bodů bude odpovídat pouze požadavkům s předponou /private/todos a vyžaduje ověření.
Objekt QueryPrivateTodospro filtrování koncových bodů je místní funkce, která upravuje parametry obslužné rutiny TodoDb trasy tak, aby umožňovala přístup k privátním datům úkolů a jejich ukládání.
Skupiny tras také podporují vnořené skupiny a složité vzory předpon s parametry trasy a omezeními. V následujícím příkladu a obslužná rutina trasy namapovaná na user skupinu může zachytit {org} parametry a {group} parametry trasy definované v předponách vnější skupiny.
Předpona může být také prázdná. To může být užitečné pro přidání metadat koncového bodu nebo filtrů do skupiny koncových bodů beze změny vzoru trasy.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
Přidání filtrů nebo metadat do skupiny se chová stejně jako jejich individuální přidání do každého koncového bodu před přidáním dalších filtrů nebo metadat, které mohly být přidány do vnitřní skupiny nebo konkrétního koncového bodu.
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);
});
V předchozím příkladu vnější filtr zapíše příchozí požadavek před vnitřním filtrem, i když byl přidán druhý. Vzhledem k tomu, že filtry byly použity u různých skupin, pořadí, které byly přidány vzhledem k sobě, nezáleží. Přidají se filtry objednávek bez ohledu na to, jestli se použije na stejnou skupinu nebo konkrétní koncový bod.
Žádost o /outer/inner/ protokolování bude následující:
/outer group filter
/inner group filter
MapGet filter
Vazba parametru
Vazba parametru je proces převodu dat požadavku na parametry silného typu, které jsou vyjádřeny obslužnými rutinami tras. Zdroj vazby určuje, odkud jsou parametry vázány. Zdroje vazeb můžou být explicitní nebo odvozené na základě metody HTTP a typu parametru.
Podporované zdroje vazeb:
- Hodnoty tras
- Řetězec dotazu
- Header
- Text (jako JSON)
- Hodnoty formuláře
- Služby poskytované injektáží závislostí
- Custom
Následující obslužná rutina trasy GET používá některé z těchto zdrojů vazeb parametrů:
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 { }
Funkce vazby klíčových parametrů
-
Explicitní vazba: Použijte atributy, jako jsou
[FromRoute],[FromQuery],[FromHeader],[FromBody],[FromForm]a[FromServices], k explicitnímu určení zdrojů vazeb. -
Vázání formuláře: Vytváření vazby hodnot formuláře pomocí
[FromForm]atributu, včetně podpory proIFormFileaIFormFileCollectionpro nahrávání souborů. - Komplexní typy: Vazba na kolekce a komplexní typy z formulářů, dotazovacích řetězců a hlaviček.
-
Vlastní vazba: Implementujte vlastní logiku vazby pomocí
TryParse,BindAsyncneboIBindableFromHttpContext<T>rozhraní. - Volitelné parametry: Podporují typy s možnou hodnotou null a výchozí hodnoty pro volitelné parametry.
- Injektáž závislostí: Parametry jsou automaticky vázány ze služeb registrovaných v kontejneru DI.
-
Speciální typy: Automatické vazby pro
HttpContext,HttpRequest,HttpResponse,CancellationToken,ClaimsPrincipal, , ,Stream, aPipeReader.
Víc se uč: Podrobné informace o vazbě parametrů, včetně pokročilých scénářů, ověření, priority vazeb a řešení potíží, najdete v tématu Vazby parametrů v aplikacích s minimálním rozhraním API.
Responses
Obslužné rutiny tras podporují následující typy návratových hodnot:
-
IResultna základě – to zahrnujeTask<IResult>aValueTask<IResult> -
string- To zahrnujeTask<string>aValueTask<string> -
T(Jakýkoli jiný typ) – to zahrnujeTask<T>aValueTask<T>
| Návratová hodnota | Behavior | Content-Type |
|---|---|---|
IResult |
Architektura volá IResult.ExecuteAsync. | Rozhodlo se implementací IResult |
string |
Architektura zapíše řetězec přímo do odpovědi. | text/plain |
T (Jakýkoli jiný typ) |
Rozhraní JSON serializuje odpověď. | application/json |
Podrobnější průvodce směrováním vrácených hodnot obslužné rutiny najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Příklad návratových hodnot
řetězcové návratové hodnoty
app.MapGet("/hello", () => "Hello World");
Návratové hodnoty JSON
app.MapGet("/hello", () => new { Message = "Hello World" });
Vrácení TypedResults
Následující kód vrátí TypedResults:
app.MapGet("/hello", () => TypedResults.Ok(new Message() { Text = "Hello World!" }));
TypedResults Vrácení je upřednostňované pro vrácení Results. Další informace naleznete v tématu TypedResults vs Výsledky.
Návratové hodnoty IResult
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Následující příklad používá předdefinované typy výsledků k přizpůsobení odpovědi:
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" }));
Vlastní stavový kó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");
});
Další příklady najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Redirect
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
File
app.MapGet("/download", () => Results.File("myfile.text"));
Předdefinované výsledky
Běžné pomocné rutiny výsledků existují ve statických ResultsTypedResults třídách.
TypedResults Vrácení je upřednostňované pro vrácení Results. Další informace naleznete v tématu TypedResults vs Výsledky.
Úprava hlaviček
Pomocí objektu HttpResponse upravte hlavičky odpovědi:
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";
});
Přizpůsobení výsledků
Aplikace můžou řídit odpovědi implementací vlastního IResult typu. Následující kód je příkladem typu výsledku HTML:
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);
}
}
Doporučujeme přidat metodu rozšíření, aby Microsoft.AspNetCore.Http.IResultExtensions byly tyto vlastní výsledky lépe zjistitelné.
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();
Zadané výsledky
Rozhraní IResult může představovat hodnoty vrácené z minimálních rozhraní API, která nevyužívají implicitní podporu pro serializaci JSON vráceného objektu do odpovědi HTTP.
Static Results třída slouží k vytvoření různých IResult objektů, které představují různé typy odpovědí. Můžete například nastavit stavový kód odpovědi nebo přesměrovat na jinou adresu URL.
Implementované IResult typy jsou veřejné, což umožňuje při testování kontrolní výrazy typů. Například:
[TestClass()]
public class WeatherApiTests
{
[TestMethod()]
public void MapWeatherApiTest()
{
var result = WeatherApi.GetAllWeathers();
Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
}
}
Můžete se podívat na návratové typy odpovídajících metod ve statické TypedResults třídy najít správný veřejný IResult typ, na který se má přetypovat.
Další příklady najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Filters
Další informace najdete v tématu Filtry v minimálních aplikacích API.
Authorization
Trasy je možné chránit pomocí zásad autorizace. Tyto můžou být deklarovány prostřednictvím atributu [Authorize] nebo pomocí RequireAuthorization metody:
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();
Předchozí kód lze napsat takto RequireAuthorization:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Následující ukázka používá autorizaci založenou na zásadách:
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();
Povolit neověřeným uživatelům přístup ke koncovému bodu
Umožňuje [AllowAnonymous] neověřeným uživatelům přístup ke koncovým bodům:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Trasy můžou být povolené CORS pomocí zásad CORS. CORS lze deklarovat prostřednictvím atributu [EnableCors] nebo pomocí RequireCors metody. Následující ukázky umožňují 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("/",() => "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();
Další informace najdete v tématu Povolení žádostí mezi zdroji (CORS) v ASP.NET Core
ValidateScopes a ValidateOnBuild
ValidateScopesa ValidateOnBuild jsou ve výchozím nastavení povolené ve vývojovém prostředí, ale jsou zakázané v jiných prostředích.
Pokud ValidateOnBuild je , truekontejner DI ověří konfiguraci služby v době sestavení. Pokud je konfigurace služby neplatná, sestavení selže při spuštění aplikace, a ne za běhu při vyžádání služby.
V ValidateScopes takovém případě truekontejner DI ověří, že služba s vymezeným oborem není přeložena z kořenového oboru. Překlad služby s vymezeným oborem z kořenového oboru může vést k nevracení paměti, protože služba je zachována v paměti delší než rozsah požadavku.
ValidateScopes a ValidateOnBuild jsou ve výchozím nastavení nepravdivé v režimech mimo vývoj z důvodů výkonu.
Následující kód je ValidateScopes ve výchozím nastavení povolený ve vývojovém režimu, ale v režimu vydání je zakázaný:
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 { }
Následující kód je ValidateOnBuild ve výchozím nastavení povolený ve vývojovém režimu, ale v režimu vydání je zakázaný:
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 { }
Následující kód zakáže ValidateScopes a ValidateOnBuild v Development:
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;
});
}
Viz také
- Stručná referenční dokumentace k minimálním rozhraním API
- Generování dokumentů OpenAPI
- Vytváření odpovědí v aplikacích s minimálním rozhraním API
- Filtry v minimálních aplikacích API
- Zpracování chyb v rozhraních API ASP.NET Core
- Ověřování a autorizace v minimálních rozhraních API
- Testování minimálních aplikací API
- Směrování zkratek
- Identity Koncové body rozhraní API
- Podpora kontejneru injektáže závislostí služby s klíči
- Pohled na minimální koncové body rozhraní API
- Uspořádání ASP.NET základních minimálních rozhraní API
- Diskuze o ověřování fluentu na GitHubu
Tento dokument:
- Poskytuje stručný přehled minimálních rozhraní API.
- Je určený pro zkušené vývojáře. Úvod najdete v tématu Kurz: Vytvoření minimálního rozhraní API s ASP.NET Core.
Minimální rozhraní API se skládají z:
WebApplication
Následující kód je generován šablonou ASP.NET Core:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Předchozí kód lze vytvořit prostřednictvím dotnet new web příkazového řádku nebo výběrem prázdné webové šablony v sadě Visual Studio.
Následující kód vytvoří WebApplication (app) bez explicitního vytvoření WebApplicationBuilder:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create inicializuje novou instanci WebApplication třídy s předkonfigurovanými výchozími nastaveními.
WebApplication automaticky přidá následující middleware v aplikacích s minimálním rozhraním API v závislosti na určitých podmínkách:
-
UseDeveloperExceptionPageje přidána jako první, pokud jeHostingEnvironment."Development" -
UseRoutingse přidá sekundu, pokud se kód uživatele ještě nevolalUseRoutinga pokud jsou nakonfigurované koncové body, napříkladapp.MapGet. -
UseEndpointsse přidá na konec kanálu middlewaru, pokud jsou nakonfigurované nějaké koncové body. -
UseAuthenticationse přidá okamžitě poUseRoutingtom, co uživatelský kód ještě nezavolalUseAuthenticationa pokudIAuthenticationSchemeProviderje možné ho zjistit v poskytovateli služeb.IAuthenticationSchemeProviderje přidána ve výchozím nastavení při použitíAddAuthenticationa služby jsou zjištěny pomocíIServiceProviderIsService. -
UseAuthorizationse přidá dál, pokud kód uživatele ještě nezavolalUseAuthorizationa pokudIAuthorizationHandlerProviderje možné ho zjistit v poskytovateli služeb.IAuthorizationHandlerProviderje přidána ve výchozím nastavení při použitíAddAuthorizationa služby jsou zjištěny pomocíIServiceProviderIsService. - Mezi uživatelem nakonfigurovaný middleware a koncové body se přidají mezi
UseRoutingaUseEndpoints.
Následující kód je v podstatě to, co automatický middleware přidaný do aplikace vytvoří:
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 => {});
V některých případech není výchozí konfigurace middlewaru pro aplikaci správná a vyžaduje úpravy. Například UseCors by mělo být volána před UseAuthentication a UseAuthorization. Aplikace musí volat UseAuthentication a UseAuthorization pokud UseCors se volá:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Pokud by se měl middleware spustit před výskytem párování tras, UseRouting měl by být volána a middleware by měl být umístěn před voláním UseRouting.
UseEndpoints v tomto případě se nevyžaduje, protože se automaticky přidá, jak je popsáno výše:
app.Use((context, next) =>
{
return next(context);
});
app.UseRouting();
// other middleware and endpoints
Při přidávání middlewaru terminálu:
- Middleware musí být přidán za
UseEndpoints. - Aplikace musí volat
UseRouting,UseEndpointsaby middleware terminálu mohl být umístěn ve správném umístění.
app.UseRouting();
app.MapGet("/", () => "hello world");
app.UseEndpoints(e => {});
app.Run(context =>
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
Middleware terminálu je middleware, který se spustí, pokud požadavek nezpracuje žádný koncový bod.
Práce s porty
Při vytvoření webové aplikace pomocí sady Visual Studio nebo dotnet newProperties/launchSettings.json se vytvoří soubor, který určuje porty, na které aplikace reaguje. V ukázkách nastavení portů, které následují, vrátí spuštění aplikace ze sady Visual Studio dialogové okno Unable to connect to web server 'AppName's chybou . Visual Studio vrátí chybu, protože očekává port zadaný v Properties/launchSettings.jsonaplikaci, ale aplikace používá port určený app.Run("http://localhost:3000"). Z příkazového řádku spusťte následující ukázky změn portů.
Následující části nastavují port, na který aplikace reaguje.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
V předchozím kódu aplikace reaguje na port 3000.
Více portů
V následujícím kódu aplikace reaguje na port 3000 a 4000.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
Nastavení portu z příkazového řádku
Následující příkaz způsobí, že aplikace reaguje na port 7777:
dotnet run --urls="https://localhost:7777"
Kestrel Pokud je koncový bod také nakonfigurovaný v appsettings.json souboru, appsettings.json použije se zadaná adresa URL. Další informace najdete v tématu Kestrel Konfigurace koncového bodu.
Čtení portu z prostředí
Následující kód načte port z prostředí:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
Upřednostňovaným způsobem nastavení portu z prostředí je použití ASPNETCORE_URLS proměnné prostředí, která je znázorněna v následující části.
Nastavení portů prostřednictvím proměnné prostředí ASPNETCORE_URLS
Proměnná ASPNETCORE_URLS prostředí je k dispozici pro nastavení portu:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS podporuje více adres URL:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
Naslouchání na všech rozhraních
Následující ukázky ukazují naslouchání na všech rozhraních.
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();
Naslouchání všem rozhraním pomocí ASPNETCORE_URLS
Předchozí ukázky můžou použít ASPNETCORE_URLS
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
Naslouchání všem rozhraním pomocí ASPNETCORE_HTTPS_PORTS
Předchozí ukázky mohou používat ASPNETCORE_HTTPS_PORTS a ASPNETCORE_HTTP_PORTS.
ASPNETCORE_HTTP_PORTS=3000;5005
ASPNETCORE_HTTPS_PORTS=5000
Další informace najdete v tématu Konfigurace koncových bodů pro webový server ASP.NET Core Kestrel .
Zadání HTTPS s vývojovým certifikátem
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Další informace o vývojovém certifikátu najdete v tématu Důvěryhodnost vývojového certifikátu ASP.NET Core HTTPS ve Windows a macOS.
Zadání HTTPS pomocí vlastního certifikátu
Následující části ukazují, jak zadat vlastní certifikát pomocí appsettings.json souboru a prostřednictvím konfigurace.
Zadání vlastního certifikátu pomocí appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Zadání vlastního certifikátu prostřednictvím konfigurace
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();
Použití rozhraní API pro certifikáty
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();
Čtení prostředí
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();
Další informace o používání prostředí najdete v tématu runtime prostředí ASP.NET Core.
Configuration
Následující kód čte z konfiguračního systému:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Config failed!";
app.MapGet("/", () => message);
app.Run();
Další informace najdete v tématu Konfigurace v ASP.NET Core
Logging
Následující kód zapíše zprávu do protokolu při spuštění aplikace:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
Další informace najdete v tématu Protokolování v .NET a ASP.NET Core
Přístup ke kontejneru injektáže závislostí (DI)
Následující kód ukazuje, jak získat služby z kontejneru DI během spouštění aplikace:
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();
Následující kód ukazuje, jak přistupovat ke klíčům z kontejneru DI pomocí atributu [FromKeyedServices] :
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.";
}
Další informace o DI naleznete v tématu Injektáž závislostí v ASP.NET Core.
WebApplicationBuilder
Tato část obsahuje vzorový kód používající WebApplicationBuilder.
Změna kořenového adresáře obsahu, názvu aplikace a prostředí
Následující kód nastaví kořen obsahu, název aplikace a prostředí:
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 inicializuje novou instanci třídy WebApplicationBuilder s předkonfigurovanými výchozími hodnotami.
Další informace najdete v tématu ASP.NET Základní základní přehled
Změna kořenového adresáře obsahu, názvu aplikace a prostředí pomocí proměnných prostředí nebo příkazového řádku
Následující tabulka ukazuje proměnnou prostředí a argument příkazového řádku použitý ke změně kořenového adresáře obsahu, názvu aplikace a prostředí:
| atribut | Proměnná prostředí | Argument příkazového řádku |
|---|---|---|
| Název aplikace | ASPNETCORE_APPLICATIONNAME | --applicationName |
| Název prostředí | ASPNETCORE_ENVIRONMENT | --environment |
| Kořenový adresář obsahu | ASPNETCORE_CONTENTROOT | --contentRoot |
Přidání zprostředkovatelů konfigurace
Následující ukázka přidá zprostředkovatele konfigurace INI:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Podrobné informace najdete v tématu Zprostředkovatelé konfigurace souborů v části Konfigurace v ASP.NET Core.
Konfigurace čtení
Ve výchozím nastavení WebApplicationBuilder konfigurace čtení z více zdrojů, včetně:
-
appSettings.jsonaappSettings.{environment}.json - Proměnné prostředí
- Příkazový řádek
Úplný seznam přečtených zdrojů konfigurace najdete v tématu Výchozí konfigurace v konfiguraci v ASP.NET Core.
Následující kód načte HelloKey z konfigurace a zobrazí hodnotu v koncovém / bodu. Pokud má konfigurační hodnota hodnotu null, je "Hello" přiřazeno k message:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
Čtení prostředí
var builder = WebApplication.CreateBuilder(args);
if (builder.Environment.IsDevelopment())
{
Console.WriteLine($"Running in development.");
}
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Přidání zprostředkovatelů protokolování
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();
Přidání služeb
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();
Přizpůsobení nástroje IHostBuilder
K existujícím metodám IHostBuilder rozšíření lze přistupovat pomocí vlastnosti Host:
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();
Přizpůsobení IWebHostBuilderu
Metody rozšíření lze IWebHostBuilder získat přístup pomocí WebApplicationBuilder.WebHost vlastnost.
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();
Změna webového kořenového adresáře
Ve výchozím nastavení je kořenový adresář webu relativní ke kořenovému wwwroot adresáři obsahu ve složce. Webový kořenový adresář je místo, kde middleware statického souboru hledá statické soubory. Kořenový adresář webu lze změnit pomocí WebHostOptionspříkazového řádku nebo pomocí UseWebRoot metody:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Kontejner injektáže vlastních závislostí (DI)
Následující příklad používá autofac:
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();
Přidání middlewaru
Jakýkoli existující middleware ASP.NET Core je možné nakonfigurovat na :WebApplication
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
Další informace najdete v tématu ASP.NET Core Middleware
Stránka výjimky pro vývojáře
WebApplication.CreateBuilder inicializuje novou instanci WebApplicationBuilder třídy s předkonfigurovanými výchozími nastaveními. Stránka výjimky vývojáře je povolená v předkonfigurovaných výchozích nastaveních. Když se ve vývojovém prostředí spustí následující kód, přejdete k / vykreslení popisné stránky, která zobrazí výjimku.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () =>
{
throw new InvalidOperationException("Oops, the '/' route has thrown an exception.");
});
app.Run();
Middleware ASP.NET Core
Následující tabulka uvádí některé z middlewarů, které se často používají s minimálními rozhraními API.
| Middleware | Description | API |
|---|---|---|
| Authentication | Poskytuje podporu ověřování. | UseAuthentication |
| Authorization | Poskytuje podporu autorizace. | UseAuthorization |
| CORS | Konfiguruje sdílení prostředků mezi zdroji (CORS). | UseCors |
| Obslužná rutina výjimky | Globálně zpracovává výjimky vyvolané kanálem middlewaru. | UseExceptionHandler |
| Přeposílané hlavičky | Předá přeposílané hlavičky do aktuálního požadavku. | UseForwardedHeaders |
| Přesměrování HTTPS | Přesměruje všechny požadavky HTTP na HTTPS. | UseHttpsRedirection |
| Zabezpečení striktního přenosu HTTP (HSTS) | Middleware pro vylepšení zabezpečení, který přidává speciální hlavičku odpovědi. | UseHsts |
| Protokolování požadavku | Poskytuje podporu protokolování požadavků a odpovědí HTTP. | UseHttpLogging |
| Časové limity požadavků | Poskytuje podporu pro konfiguraci časových limitů požadavků, globálního výchozího a koncového bodu. | UseRequestTimeouts |
| Protokolování požadavků W3C | Poskytuje podporu pro protokolování požadavků HTTP a odpovědí ve formátu W3C. | UseW3CLogging |
| Ukládání odpovědí do mezipaměti | Poskytuje podporu pro ukládání odpovědí do mezipaměti. | UseResponseCaching |
| Komprese odpovědí | Poskytuje podporu pro kompresi odpovědí. | UseResponseCompression |
| Session | Poskytuje podporu pro správu uživatelských relací. | UseSession |
| Statické soubory | Poskytuje podporu pro obsluhu statických souborů a procházení adresářů. | UseStaticFiles, UseFileServer |
| WebSockets | Povoluje protokol WebSocket. | UseWebSockets |
Následující části zahrnují zpracování požadavků: směrování, vazby parametrů a odpovědi.
Routing
Nakonfigurovaná podpora a kde je metoda HTTP typu camel-cased, například WebApplication, Map{Verb}nebo MapMethods{Verb}:GetPostPutDelete
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();
Argumenty Delegate předané těmto metodám se nazývají "obslužné rutiny tras".
Obslužné rutiny tras
Obslužné rutiny tras jsou metody, které se spouštějí, když se trasa shoduje. Obslužné rutiny tras mohou být výraz lambda, místní funkce, metoda instance nebo statická metoda. Obslužné rutiny tras můžou být synchronní nebo asynchronní.
Výraz lambda
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();
Místní funkce
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Metoda instance
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";
}
}
Statická metoda
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";
}
}
Koncový bod definovaný mimo Program.cs
Minimální rozhraní API nemusí být umístěna v Program.csumístění .
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" });
});
}
}
Viz také skupiny Směrování dále v tomto článku.
Pojmenované koncové body a generování propojení
Koncové body můžou mít názvy, aby se vygenerovaly adresy URL koncového bodu. Použitím pojmenovaného koncového bodu se v aplikaci nemusíte pevně zakódovat cesty:
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();
Předchozí kód se zobrazí The link to the hello route is /hello z koncového / bodu.
POZNÁMKA: V názvech koncových bodů se rozlišují malá a velká písmena.
Názvy koncových bodů:
- Musí být globálně jedinečný.
- Používají se jako ID operace OpenAPI, pokud je povolená podpora OpenAPI. Další informace najdete v tématu OpenAPI.
Parametry trasy
Parametry trasy je možné zachytit jako součást definice vzoru trasy:
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();
Předchozí kód vrátí The user id is 3 and book id is 7 z identifikátoru URI /users/3/books/7.
Obslužná rutina trasy může deklarovat parametry, které se mají zachytit. Při provedení požadavku na trasu s parametry deklarovanými k zachycení se parametry parsují a předávají obslužné rutině. To usnadňuje zachytávání hodnot v bezpečném typu. V předchozím kódu userId a bookId jsou oba int.
Pokud v předchozím kódu nelze převést intna některou hodnotu trasy , vyvolá se výjimka. Požadavek /users/hello/books/3 GET vyvolá následující výjimku:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Zástupný znak a zachycení všech tras
Následující zachytávání všech návratových tras Routing to hello z koncového bodu /posts/hello:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Omezení trasy
Omezení trasy omezují odpovídající chování trasy.
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();
Následující tabulka ukazuje předchozí šablony tras a jejich chování:
| Šablona trasy | Příklad odpovídajícího identifikátoru URI |
|---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
Další informace najdete v tématu Referenční informace o omezení trasy ve směrování v ASP.NET Core.
Skupiny tras
Metoda MapGroup rozšíření pomáhá uspořádat skupiny koncových bodů s běžnou předponou. Snižuje opakující se kód a umožňuje přizpůsobit celé skupiny koncových bodů jediným voláním metod, jako RequireAuthorization jsou a WithMetadata které přidávají metadata koncového bodu.
Například následující kód vytvoří dvě podobné skupiny koncových bodů:
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;
}
V tomto scénáři můžete použít relativní adresu hlavičky Location ve výsledku 201 Created :
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
První skupina koncových bodů se bude shodovat pouze s požadavky s předponou /public/todos a jsou přístupná bez ověřování. Druhá skupina koncových bodů bude odpovídat pouze požadavkům s předponou /private/todos a vyžaduje ověření.
Objekt QueryPrivateTodospro filtrování koncových bodů je místní funkce, která upravuje parametry obslužné rutiny TodoDb trasy tak, aby umožňovala přístup k privátním datům úkolů a jejich ukládání.
Skupiny tras také podporují vnořené skupiny a složité vzory předpon s parametry trasy a omezeními. V následujícím příkladu a obslužná rutina trasy namapovaná na user skupinu může zachytit {org} parametry a {group} parametry trasy definované v předponách vnější skupiny.
Předpona může být také prázdná. To může být užitečné pro přidání metadat koncového bodu nebo filtrů do skupiny koncových bodů beze změny vzoru trasy.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
Přidání filtrů nebo metadat do skupiny se chová stejně jako jejich individuální přidání do každého koncového bodu před přidáním dalších filtrů nebo metadat, které mohly být přidány do vnitřní skupiny nebo konkrétního koncového bodu.
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);
});
V předchozím příkladu vnější filtr zapíše příchozí požadavek před vnitřním filtrem, i když byl přidán druhý. Vzhledem k tomu, že filtry byly použity u různých skupin, pořadí, které byly přidány vzhledem k sobě, nezáleží. Přidají se filtry objednávek bez ohledu na to, jestli se použije na stejnou skupinu nebo konkrétní koncový bod.
Žádost o /outer/inner/ protokolování bude následující:
/outer group filter
/inner group filter
MapGet filter
Vazba parametru
Vazba parametru je proces převodu dat požadavku na parametry silného typu, které jsou vyjádřeny obslužnými rutinami tras. Zdroj vazby určuje, odkud jsou parametry vázány. Zdroje vazeb můžou být explicitní nebo odvozené na základě metody HTTP a typu parametru.
Podporované zdroje vazeb:
- Hodnoty tras
- Řetězec dotazu
- Header
- Text (jako JSON)
- Hodnoty formuláře
- Služby poskytované injektáží závislostí
- Custom
Následující obslužná rutina trasy GET používá některé z těchto zdrojů vazeb parametrů:
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 { }
Funkce vazby klíčových parametrů
-
Explicitní vazba: Použijte atributy, jako jsou
[FromRoute],[FromQuery],[FromHeader],[FromBody],[FromForm]a[FromServices], k explicitnímu určení zdrojů vazeb. -
Vázání formuláře: Vytváření vazby hodnot formuláře pomocí
[FromForm]atributu, včetně podpory proIFormFileaIFormFileCollectionpro nahrávání souborů. - Komplexní typy: Vazba na kolekce a komplexní typy z formulářů, dotazovacích řetězců a hlaviček.
-
Vlastní vazba: Implementujte vlastní logiku vazby pomocí
TryParse,BindAsyncneboIBindableFromHttpContext<T>rozhraní. - Volitelné parametry: Podporují typy s možnou hodnotou null a výchozí hodnoty pro volitelné parametry.
- Injektáž závislostí: Parametry jsou automaticky vázány ze služeb registrovaných v kontejneru DI.
-
Speciální typy: Automatické vazby pro
HttpContext,HttpRequest,HttpResponse,CancellationToken,ClaimsPrincipal, , ,Stream, aPipeReader.
Víc se uč: Podrobné informace o vazbě parametrů, včetně pokročilých scénářů, ověření, priority vazeb a řešení potíží, najdete v tématu Vazby parametrů v aplikacích s minimálním rozhraním API.
Responses
Obslužné rutiny tras podporují následující typy návratových hodnot:
-
IResultna základě – to zahrnujeTask<IResult>aValueTask<IResult> -
string- To zahrnujeTask<string>aValueTask<string> -
T(Jakýkoli jiný typ) – to zahrnujeTask<T>aValueTask<T>
| Návratová hodnota | Behavior | Content-Type |
|---|---|---|
IResult |
Architektura volá IResult.ExecuteAsync. | Rozhodlo se implementací IResult |
string |
Architektura zapíše řetězec přímo do odpovědi. | text/plain |
T (Jakýkoli jiný typ) |
Rozhraní JSON serializuje odpověď. | application/json |
Podrobnější průvodce směrováním vrácených hodnot obslužné rutiny najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Příklad návratových hodnot
řetězcové návratové hodnoty
app.MapGet("/hello", () => "Hello World");
Návratové hodnoty JSON
app.MapGet("/hello", () => new { Message = "Hello World" });
Vrácení TypedResults
Následující kód vrátí TypedResults:
app.MapGet("/hello", () => TypedResults.Ok(new Message() { Text = "Hello World!" }));
TypedResults Vrácení je upřednostňované pro vrácení Results. Další informace naleznete v tématu TypedResults vs Výsledky.
Návratové hodnoty IResult
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Následující příklad používá předdefinované typy výsledků k přizpůsobení odpovědi:
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" }));
Vlastní stavový kó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");
});
Další příklady najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Redirect
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
File
app.MapGet("/download", () => Results.File("myfile.text"));
Předdefinované výsledky
Běžné pomocné rutiny výsledků existují ve statických ResultsTypedResults třídách.
TypedResults Vrácení je upřednostňované pro vrácení Results. Další informace naleznete v tématu TypedResults vs Výsledky.
Úprava hlaviček
Pomocí objektu HttpResponse upravte hlavičky odpovědi:
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";
});
Přizpůsobení výsledků
Aplikace můžou řídit odpovědi implementací vlastního IResult typu. Následující kód je příkladem typu výsledku HTML:
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);
}
}
Doporučujeme přidat metodu rozšíření, aby Microsoft.AspNetCore.Http.IResultExtensions byly tyto vlastní výsledky lépe zjistitelné.
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();
Zadané výsledky
Rozhraní IResult může představovat hodnoty vrácené z minimálních rozhraní API, která nevyužívají implicitní podporu pro serializaci JSON vráceného objektu do odpovědi HTTP.
Static Results třída slouží k vytvoření různých IResult objektů, které představují různé typy odpovědí. Můžete například nastavit stavový kód odpovědi nebo přesměrovat na jinou adresu URL.
Implementované IResult typy jsou veřejné, což umožňuje při testování kontrolní výrazy typů. Například:
[TestClass()]
public class WeatherApiTests
{
[TestMethod()]
public void MapWeatherApiTest()
{
var result = WeatherApi.GetAllWeathers();
Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
}
}
Můžete se podívat na návratové typy odpovídajících metod ve statické TypedResults třídy najít správný veřejný IResult typ, na který se má přetypovat.
Další příklady najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Filters
Další informace najdete v tématu Filtry v minimálních aplikacích API.
Authorization
Trasy je možné chránit pomocí zásad autorizace. Tyto můžou být deklarovány prostřednictvím atributu [Authorize] nebo pomocí RequireAuthorization metody:
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();
Předchozí kód lze napsat takto RequireAuthorization:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Následující ukázka používá autorizaci založenou na zásadách:
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();
Povolit neověřeným uživatelům přístup ke koncovému bodu
Umožňuje [AllowAnonymous] neověřeným uživatelům přístup ke koncovým bodům:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Trasy můžou být povolené CORS pomocí zásad CORS. CORS lze deklarovat prostřednictvím atributu [EnableCors] nebo pomocí RequireCors metody. Následující ukázky umožňují 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("/",() => "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();
Další informace najdete v tématu Povolení žádostí mezi zdroji (CORS) v ASP.NET Core
ValidateScopes a ValidateOnBuild
ValidateScopesa ValidateOnBuild jsou ve výchozím nastavení povolené ve vývojovém prostředí, ale jsou zakázané v jiných prostředích.
Pokud ValidateOnBuild je , truekontejner DI ověří konfiguraci služby v době sestavení. Pokud je konfigurace služby neplatná, sestavení selže při spuštění aplikace, a ne za běhu při vyžádání služby.
V ValidateScopes takovém případě truekontejner DI ověří, že služba s vymezeným oborem není přeložena z kořenového oboru. Překlad služby s vymezeným oborem z kořenového oboru může vést k nevracení paměti, protože služba je zachována v paměti delší než rozsah požadavku.
ValidateScopes a ValidateOnBuild jsou ve výchozím nastavení nepravdivé v režimech mimo vývoj z důvodů výkonu.
Následující kód je ValidateScopes ve výchozím nastavení povolený ve vývojovém režimu, ale v režimu vydání je zakázaný:
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 { }
Následující kód je ValidateOnBuild ve výchozím nastavení povolený ve vývojovém režimu, ale v režimu vydání je zakázaný:
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 { }
Následující kód zakáže ValidateScopes a ValidateOnBuild v Development:
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;
});
}
Viz také
- Stručná referenční dokumentace k minimálním rozhraním API
- Generování dokumentů OpenAPI
- Vytváření odpovědí v aplikacích s minimálním rozhraním API
- Filtry v minimálních aplikacích API
- Zpracování chyb v rozhraních API ASP.NET Core
- Ověřování a autorizace v minimálních rozhraních API
- Testování minimálních aplikací API
- Směrování zkratek
- Identity Koncové body rozhraní API
- Podpora kontejneru injektáže závislostí služby s klíči
- Pohled na minimální koncové body rozhraní API
- Uspořádání ASP.NET základních minimálních rozhraní API
- Diskuze o ověřování fluentu na GitHubu
Tento dokument:
- Poskytuje stručný přehled minimálních rozhraní API.
- Je určený pro zkušené vývojáře. Úvod najdete v tématu Kurz: Vytvoření minimálního rozhraní API s ASP.NET Core
Minimální rozhraní API se skládají z:
WebApplication
Následující kód je generován šablonou ASP.NET Core:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Předchozí kód lze vytvořit prostřednictvím dotnet new web příkazového řádku nebo výběrem prázdné webové šablony v sadě Visual Studio.
Následující kód vytvoří WebApplication (app) bez explicitního vytvoření WebApplicationBuilder:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create inicializuje novou instanci WebApplication třídy s předkonfigurovanými výchozími nastaveními.
WebApplication automaticky přidá následující middleware v aplikacích s minimálním rozhraním API v závislosti na určitých podmínkách:
-
UseDeveloperExceptionPageje přidána jako první, pokud jeHostingEnvironment."Development" -
UseRoutingse přidá sekundu, pokud se kód uživatele ještě nevolalUseRoutinga pokud jsou nakonfigurované koncové body, napříkladapp.MapGet. -
UseEndpointsse přidá na konec kanálu middlewaru, pokud jsou nakonfigurované nějaké koncové body. -
UseAuthenticationse přidá okamžitě poUseRoutingtom, co uživatelský kód ještě nezavolalUseAuthenticationa pokudIAuthenticationSchemeProviderje možné ho zjistit v poskytovateli služeb.IAuthenticationSchemeProviderje přidána ve výchozím nastavení při použitíAddAuthenticationa služby jsou zjištěny pomocíIServiceProviderIsService. -
UseAuthorizationse přidá dál, pokud kód uživatele ještě nezavolalUseAuthorizationa pokudIAuthorizationHandlerProviderje možné ho zjistit v poskytovateli služeb.IAuthorizationHandlerProviderje přidána ve výchozím nastavení při použitíAddAuthorizationa služby jsou zjištěny pomocíIServiceProviderIsService. - Mezi uživatelem nakonfigurovaný middleware a koncové body se přidají mezi
UseRoutingaUseEndpoints.
Následující kód je v podstatě to, co automatický middleware přidaný do aplikace vytvoří:
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 => {});
V některých případech není výchozí konfigurace middlewaru pro aplikaci správná a vyžaduje úpravy. Například UseCors by mělo být volána před UseAuthentication a UseAuthorization. Aplikace musí volat UseAuthentication a UseAuthorization pokud UseCors se volá:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Pokud by se měl middleware spustit před výskytem párování tras, UseRouting měl by být volána a middleware by měl být umístěn před voláním UseRouting.
UseEndpoints v tomto případě se nevyžaduje, protože se automaticky přidá, jak je popsáno výše:
app.Use((context, next) =>
{
return next(context);
});
app.UseRouting();
// other middleware and endpoints
Při přidávání middlewaru terminálu:
- Middleware musí být přidán za
UseEndpoints. - Aplikace musí volat
UseRouting,UseEndpointsaby middleware terminálu mohl být umístěn ve správném umístění.
app.UseRouting();
app.MapGet("/", () => "hello world");
app.UseEndpoints(e => {});
app.Run(context =>
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
Middleware terminálu je middleware, který se spustí, pokud požadavek nezpracuje žádný koncový bod.
Práce s porty
Při vytvoření webové aplikace pomocí sady Visual Studio nebo dotnet newProperties/launchSettings.json se vytvoří soubor, který určuje porty, na které aplikace reaguje. V ukázkách nastavení portů, které následují, vrátí spuštění aplikace ze sady Visual Studio dialogové okno Unable to connect to web server 'AppName's chybou . Visual Studio vrátí chybu, protože očekává port zadaný v Properties/launchSettings.jsonaplikaci, ale aplikace používá port určený app.Run("http://localhost:3000"). Z příkazového řádku spusťte následující ukázky změn portů.
Následující části nastavují port, na který aplikace reaguje.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
V předchozím kódu aplikace reaguje na port 3000.
Více portů
V následujícím kódu aplikace reaguje na port 3000 a 4000.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
Nastavení portu z příkazového řádku
Následující příkaz způsobí, že aplikace reaguje na port 7777:
dotnet run --urls="https://localhost:7777"
Kestrel Pokud je koncový bod také nakonfigurovaný v appsettings.json souboru, appsettings.json použije se zadaná adresa URL. Další informace najdete v tématu Kestrel Konfigurace koncového bodu.
Čtení portu z prostředí
Následující kód načte port z prostředí:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
Upřednostňovaným způsobem nastavení portu z prostředí je použití ASPNETCORE_URLS proměnné prostředí, která je znázorněna v následující části.
Nastavení portů prostřednictvím proměnné prostředí ASPNETCORE_URLS
Proměnná ASPNETCORE_URLS prostředí je k dispozici pro nastavení portu:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS podporuje více adres URL:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
Další informace o používání prostředí najdete v tématu runtime prostředí ASP.NET Core.
Naslouchání na všech rozhraních
Následující ukázky ukazují naslouchání na všech rozhraních.
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();
Naslouchání všem rozhraním pomocí ASPNETCORE_URLS
Předchozí ukázky můžou použít ASPNETCORE_URLS
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
Zadání HTTPS s vývojovým certifikátem
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Další informace o vývojovém certifikátu najdete v tématu Důvěryhodnost vývojového certifikátu ASP.NET Core HTTPS ve Windows a macOS.
Zadání HTTPS pomocí vlastního certifikátu
Následující části ukazují, jak zadat vlastní certifikát pomocí appsettings.json souboru a prostřednictvím konfigurace.
Zadání vlastního certifikátu pomocí appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Zadání vlastního certifikátu prostřednictvím konfigurace
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();
Použití rozhraní API pro certifikáty
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
Následující kód čte z konfiguračního systému:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Config failed!";
app.MapGet("/", () => message);
app.Run();
Další informace najdete v tématu Konfigurace v ASP.NET Core
Logging
Následující kód zapíše zprávu do protokolu při spuštění aplikace:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
Další informace najdete v tématu Protokolování v .NET a ASP.NET Core
Přístup ke kontejneru injektáže závislostí (DI)
Následující kód ukazuje, jak získat služby z kontejneru DI během spouštění aplikace:
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();
Další informace naleznete v tématu Injektáž závislostí v ASP.NET Core.
WebApplicationBuilder
Tato část obsahuje vzorový kód používající WebApplicationBuilder.
Změna kořenového adresáře obsahu, názvu aplikace a prostředí
Následující kód nastaví kořen obsahu, název aplikace a prostředí:
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 inicializuje novou instanci třídy WebApplicationBuilder s předkonfigurovanými výchozími hodnotami.
Další informace najdete v tématu ASP.NET Základní základní přehled
Změna kořenového adresáře obsahu, názvu aplikace a prostředí podle proměnných prostředí nebo příkazového řádku
Následující tabulka ukazuje proměnnou prostředí a argument příkazového řádku použitý ke změně kořenového adresáře obsahu, názvu aplikace a prostředí:
| atribut | Proměnná prostředí | Argument příkazového řádku |
|---|---|---|
| Název aplikace | ASPNETCORE_APPLICATIONNAME | --applicationName |
| Název prostředí | ASPNETCORE_ENVIRONMENT | --environment |
| Kořenový adresář obsahu | ASPNETCORE_CONTENTROOT | --contentRoot |
Přidání zprostředkovatelů konfigurace
Následující ukázka přidá zprostředkovatele konfigurace INI:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Podrobné informace najdete v tématu Zprostředkovatelé konfigurace souborů v části Konfigurace v ASP.NET Core.
Konfigurace čtení
Ve výchozím nastavení WebApplicationBuilder konfigurace čtení z více zdrojů, včetně:
-
appSettings.jsonaappSettings.{environment}.json - Proměnné prostředí
- Příkazový řádek
Následující kód načte HelloKey z konfigurace a zobrazí hodnotu v koncovém / bodu. Pokud má konfigurační hodnota hodnotu null, je "Hello" přiřazeno k message:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
Úplný seznam přečtených zdrojů konfigurace najdete v tématu Výchozí konfigurace v konfiguraci v ASP.NET Core.
Přidání zprostředkovatelů protokolování
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();
Přidání služeb
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();
Přizpůsobení nástroje IHostBuilder
K existujícím metodám IHostBuilder rozšíření lze přistupovat pomocí vlastnosti Host:
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();
Přizpůsobení IWebHostBuilderu
Metody rozšíření lze IWebHostBuilder získat přístup pomocí WebApplicationBuilder.WebHost vlastnost.
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();
Změna webového kořenového adresáře
Ve výchozím nastavení je kořenový adresář webu relativní ke kořenovému wwwroot adresáři obsahu ve složce. Webový kořenový adresář je místo, kde middleware statického souboru hledá statické soubory. Kořenový adresář webu lze změnit pomocí WebHostOptionspříkazového řádku nebo pomocí UseWebRoot metody:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Kontejner injektáže vlastních závislostí (DI)
Následující příklad používá autofac:
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();
Přidání middlewaru
Jakýkoli existující middleware ASP.NET Core je možné nakonfigurovat na :WebApplication
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
Další informace najdete v tématu ASP.NET Core Middleware
Stránka výjimky pro vývojáře
WebApplication.CreateBuilder inicializuje novou instanci WebApplicationBuilder třídy s předkonfigurovanými výchozími nastaveními. Stránka výjimky vývojáře je povolená v předkonfigurovaných výchozích nastaveních. Když se ve vývojovém prostředí spustí následující kód, přejdete k / vykreslení popisné stránky, která zobrazí výjimku.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () =>
{
throw new InvalidOperationException("Oops, the '/' route has thrown an exception.");
});
app.Run();
Middleware ASP.NET Core
Následující tabulka uvádí některé z middlewarů, které se často používají s minimálními rozhraními API.
| Middleware | Description | API |
|---|---|---|
| Authentication | Poskytuje podporu ověřování. | UseAuthentication |
| Authorization | Poskytuje podporu autorizace. | UseAuthorization |
| CORS | Konfiguruje sdílení prostředků mezi zdroji (CORS). | UseCors |
| Obslužná rutina výjimky | Globálně zpracovává výjimky vyvolané kanálem middlewaru. | UseExceptionHandler |
| Přeposílané hlavičky | Předá přeposílané hlavičky do aktuálního požadavku. | UseForwardedHeaders |
| Přesměrování HTTPS | Přesměruje všechny požadavky HTTP na HTTPS. | UseHttpsRedirection |
| Zabezpečení striktního přenosu HTTP (HSTS) | Middleware pro vylepšení zabezpečení, který přidává speciální hlavičku odpovědi. | UseHsts |
| Protokolování požadavku | Poskytuje podporu protokolování požadavků a odpovědí HTTP. | UseHttpLogging |
| Časové limity požadavků | Poskytuje podporu pro konfiguraci časových limitů požadavků, globálního výchozího a koncového bodu. | UseRequestTimeouts |
| Protokolování požadavků W3C | Poskytuje podporu pro protokolování požadavků HTTP a odpovědí ve formátu W3C. | UseW3CLogging |
| Ukládání odpovědí do mezipaměti | Poskytuje podporu pro ukládání odpovědí do mezipaměti. | UseResponseCaching |
| Komprese odpovědí | Poskytuje podporu pro kompresi odpovědí. | UseResponseCompression |
| Session | Poskytuje podporu pro správu uživatelských relací. | UseSession |
| Statické soubory | Poskytuje podporu pro obsluhu statických souborů a procházení adresářů. | UseStaticFiles, UseFileServer |
| WebSockets | Povoluje protokol WebSocket. | UseWebSockets |
Následující části zahrnují zpracování požadavků: směrování, vazby parametrů a odpovědi.
Routing
Nakonfigurovaná podpora a kde je metoda HTTP typu camel-cased, například WebApplication, Map{Verb}nebo MapMethods{Verb}:GetPostPutDelete
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();
Argumenty Delegate předané těmto metodám se nazývají "obslužné rutiny tras".
Obslužné rutiny tras
Obslužné rutiny tras jsou metody, které se spouštějí, když se trasa shoduje. Obslužné rutiny tras mohou být výraz lambda, místní funkce, metoda instance nebo statická metoda. Obslužné rutiny tras můžou být synchronní nebo asynchronní.
Výraz lambda
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();
Místní funkce
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Metoda instance
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";
}
}
Statická metoda
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";
}
}
Koncový bod definovaný mimo Program.cs
Minimální rozhraní API nemusí být umístěna v Program.csumístění .
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" });
});
}
}
Viz také skupiny Směrování dále v tomto článku.
Pojmenované koncové body a generování propojení
Koncové body můžou mít názvy, aby se vygenerovaly adresy URL koncového bodu. Použitím pojmenovaného koncového bodu se v aplikaci nemusíte pevně zakódovat cesty:
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();
Předchozí kód se zobrazí The link to the hello route is /hello z koncového / bodu.
POZNÁMKA: V názvech koncových bodů se rozlišují malá a velká písmena.
Názvy koncových bodů:
- Musí být globálně jedinečný.
- Používají se jako ID operace OpenAPI, pokud je povolená podpora OpenAPI. Další informace najdete v tématu OpenAPI.
Parametry trasy
Parametry trasy je možné zachytit jako součást definice vzoru trasy:
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();
Předchozí kód vrátí The user id is 3 and book id is 7 z identifikátoru URI /users/3/books/7.
Obslužná rutina trasy může deklarovat parametry, které se mají zachytit. Při provedení požadavku na trasu s parametry deklarovanými k zachycení se parametry parsují a předávají obslužné rutině. To usnadňuje zachytávání hodnot v bezpečném typu. V předchozím kódu userId a bookId jsou oba int.
Pokud v předchozím kódu nelze převést intna některou hodnotu trasy , vyvolá se výjimka. Požadavek /users/hello/books/3 GET vyvolá následující výjimku:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Zástupný znak a zachycení všech tras
Následující zachytávání všech návratových tras Routing to hello z koncového bodu /posts/hello:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Omezení trasy
Omezení trasy omezují odpovídající chování trasy.
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();
Následující tabulka ukazuje předchozí šablony tras a jejich chování:
| Šablona trasy | Příklad odpovídajícího identifikátoru URI |
|---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
Další informace najdete v tématu Referenční informace o omezení trasy ve směrování v ASP.NET Core.
Skupiny tras
Metoda MapGroup rozšíření pomáhá uspořádat skupiny koncových bodů s běžnou předponou. Snižuje opakující se kód a umožňuje přizpůsobit celé skupiny koncových bodů jediným voláním metod, jako RequireAuthorization jsou a WithMetadata které přidávají metadata koncového bodu.
Například následující kód vytvoří dvě podobné skupiny koncových bodů:
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;
}
V tomto scénáři můžete použít relativní adresu hlavičky Location ve výsledku 201 Created :
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
První skupina koncových bodů se bude shodovat pouze s požadavky s předponou /public/todos a jsou přístupná bez ověřování. Druhá skupina koncových bodů bude odpovídat pouze požadavkům s předponou /private/todos a vyžaduje ověření.
Objekt QueryPrivateTodospro filtrování koncových bodů je místní funkce, která upravuje parametry obslužné rutiny TodoDb trasy tak, aby umožňovala přístup k privátním datům úkolů a jejich ukládání.
Skupiny tras také podporují vnořené skupiny a složité vzory předpon s parametry trasy a omezeními. V následujícím příkladu a obslužná rutina trasy namapovaná na user skupinu může zachytit {org} parametry a {group} parametry trasy definované v předponách vnější skupiny.
Předpona může být také prázdná. To může být užitečné pro přidání metadat koncového bodu nebo filtrů do skupiny koncových bodů beze změny vzoru trasy.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
Přidání filtrů nebo metadat do skupiny se chová stejně jako jejich individuální přidání do každého koncového bodu před přidáním dalších filtrů nebo metadat, které mohly být přidány do vnitřní skupiny nebo konkrétního koncového bodu.
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);
});
V předchozím příkladu vnější filtr zapíše příchozí požadavek před vnitřním filtrem, i když byl přidán druhý. Vzhledem k tomu, že filtry byly použity u různých skupin, pořadí, které byly přidány vzhledem k sobě, nezáleží. Přidají se filtry objednávek bez ohledu na to, jestli se použije na stejnou skupinu nebo konkrétní koncový bod.
Žádost o /outer/inner/ protokolování bude následující:
/outer group filter
/inner group filter
MapGet filter
Vazba parametru
Vazba parametru je proces převodu dat požadavku na parametry silného typu, které jsou vyjádřeny obslužnými rutinami tras. Zdroj vazby určuje, odkud jsou parametry vázány. Zdroje vazeb můžou být explicitní nebo odvozené na základě metody HTTP a typu parametru.
Podporované zdroje vazeb:
- Hodnoty tras
- Řetězec dotazu
- Header
- Text (jako JSON)
- Služby poskytované injektáží závislostí
- Custom
Vazba z hodnot formulářů není nativně podporována v .NET 6 a 7.
Následující GET obslužná rutina trasy používá některé z těchto zdrojů vazeb parametrů:
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 { }
Následující tabulka ukazuje vztah mezi parametry použitými v předchozím příkladu a přidruženými zdroji vazeb.
| Parameter | Zdroj vazby |
|---|---|
id |
hodnota trasy |
page |
řetězec dotazu |
customHeader |
hlavička |
service |
Poskytuje injektáž závislostí |
Metody GETHTTP , HEAD, OPTIONSa DELETE nejsou implicitně vázány z těla. Pokud chcete vytvořit vazbu z textu (jako JSON) pro tyto metody HTTP, vytvořte vazbu explicitně s [FromBody] použitím nebo čtením z objektu HttpRequest.
Následující příklad obslužné rutiny trasy POST používá pro parametr zdroj vazby těla (jako JSON):person
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/", (Person person) => { });
record Person(string Name, int Age);
Parametry v předchozích příkladech jsou všechny vázány z dat požadavku automaticky. Abychom si ukázali pohodlí, které poskytuje vazba parametrů, následující obslužné rutiny tras ukazují, jak číst data požadavku přímo z požadavku:
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>();
// ...
});
Explicitní vazba parametru
Atributy lze použít k explicitní deklaraci, kde jsou parametry vázány.
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 | Zdroj vazby |
|---|---|
id |
hodnota trasy s názvem id |
page |
řetězec dotazu s názvem "p" |
service |
Poskytuje injektáž závislostí |
contentType |
hlavička s názvem "Content-Type" |
Note
Vazba z hodnot formulářů není nativně podporována v .NET 6 a 7.
Vazba parametru s injektáží závislostí
Vazba parametrů pro minimální rozhraní API vytvoří vazbu parametrů prostřednictvím injektáže závislostí, když je typ nakonfigurovaný jako služba. Atribut není nutné explicitně použít [FromServices] u parametru. V následujícím kódu vrátí obě akce čas:
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();
Volitelné parametry
Parametry deklarované v obslužných rutinách tras se považují za povinné:
- Pokud požadavek odpovídá trase, obslužná rutina trasy se spustí pouze v případě, že jsou v požadavku zadány všechny požadované parametry.
- Při zadání všech požadovaných parametrů dojde k chybě.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int pageNumber) => $"Requesting page {pageNumber}");
app.Run();
| identifikátor URI | result |
|---|---|
/products?pageNumber=3 |
Vráceno 3 |
/products |
BadHttpRequestException: Požadovaný parametr int pageNumber nebyl z řetězce dotazu zadaný. |
/products/1 |
Chyba HTTP 404, žádná odpovídající trasa |
Pokud chcete nastavit pageNumber jako volitelný, definujte typ jako volitelný nebo zadejte výchozí hodnotu:
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();
| identifikátor URI | result |
|---|---|
/products?pageNumber=3 |
Vráceno 3 |
/products |
1 vráceno |
/products2 |
1 vráceno |
Předchozí hodnota s možnou hodnotou null a výchozí hodnotou platí pro všechny zdroje:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/products", (Product? product) => { });
app.Run();
Předchozí kód volá metodu s produktem null, pokud není odeslán žádný text požadavku.
POZNÁMKA: Pokud jsou zadána neplatná data a parametr má hodnotu null, obslužná rutina trasy se nespustí .
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int? pageNumber) => $"Requesting page {pageNumber ?? 1}");
app.Run();
| identifikátor URI | result |
|---|---|
/products?pageNumber=3 |
3 vrácený |
/products |
1 vrácený |
/products?pageNumber=two |
BadHttpRequestException: Nepodařilo se vytvořit vazbu parametru "Nullable<int> pageNumber" ze dvou. |
/products/two |
Chyba HTTP 404, žádná odpovídající trasa |
Další informace najdete v části Selhání vazeb.
Speciální typy
Následující typy jsou vázané bez explicitních atributů:
HttpContext: Kontext, který obsahuje všechny informace o aktuálním požadavku HTTP nebo odpovědi:
app.MapGet("/", (HttpContext context) => context.Response.WriteAsync("Hello World"));HttpRequest a HttpResponse: Požadavek HTTP a odpověď HTTP:
app.MapGet("/", (HttpRequest request, HttpResponse response) => response.WriteAsync($"Hello World {request.Query["name"]}"));CancellationToken: Token zrušení přidružený k aktuálnímu požadavku HTTP:
app.MapGet("/", async (CancellationToken cancellationToken) => await MakeLongRunningRequestAsync(cancellationToken));ClaimsPrincipal: Uživatel přidružený k požadavku vázanému z HttpContext.User:
app.MapGet("/", (ClaimsPrincipal user) => user.Identity.Name);
Vytvoření vazby textu požadavku jako nebo StreamPipeReader
Tělo požadavku může svázat jako Stream scénáře nebo PipeReader efektivně podporovat scénáře, kdy uživatel musí zpracovávat data a:
- Uložte data do úložiště objektů blob nebo vytvořte frontu dat poskytovateli fronty.
- Zpracování uložených dat pomocí pracovního procesu nebo cloudové funkce
Data můžou být například zařazená do fronty Azure Storage nebo uložená ve službě Azure Blob Storage.
Následující kód implementuje frontu na pozadí:
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;
}
Následující kód vytvoří vazbu textu požadavku na Stream:
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);
});
Následující kód ukazuje úplný Program.cs soubor:
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();
- Při čtení dat je stejný
Streamobjekt jakoHttpRequest.Body. - Tělo požadavku se ve výchozím nastavení neuloží do vyrovnávací paměti. Po přečtení těla se nedá převinout zpět. Stream nejde číst vícekrát.
- A
StreamPipeReadernejsou použitelné mimo minimální obslužnou rutinu akce, protože podkladové vyrovnávací paměti budou uvolněny nebo znovu použity.
Nahrávání souborů pomocí IFormFile a IFormFileCollection
Následující kód používá IFormFile a IFormFileCollection nahrává soubor:
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();
Žádosti o nahrání ověřených souborů se podporují pomocí autorizační hlavičky, klientského certifikátu nebo hlavičky cookie .
V rozhraní .NET 7 neexistuje žádná integrovaná podpora antiforgery v ASP.NET Core.
Antiforgery je k dispozici v ASP.NET Core v .NET 8 nebo novější. Dá se ale implementovat pomocí IAntiforgery služby.
Vytvoření vazby polí a řetězcových hodnot ze záhlaví a řetězců dotazu
Následující kód ukazuje vazby řetězců dotazu na pole primitivních typů, řetězcových polí a StringValues:
// 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]}");
Vazby řetězců dotazu nebo hodnot hlaviček na pole komplexních typů se podporují, když je TryParse typ implementovaný. Následující kód se sváže s řetězcovým polem a vrátí všechny položky se zadanými značkami:
// 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();
});
Následující kód ukazuje model a požadovanou TryParse implementaci:
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;
}
}
Následující kód se sváže s polem int :
// 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();
});
Pokud chcete otestovat předchozí kód, přidejte následující koncový bod pro naplnění databáze položkami Todo :
// POST /todoitems/batch
app.MapPost("/todoitems/batch", async (Todo[] todos, TodoDb db) =>
{
await db.Todos.AddRangeAsync(todos);
await db.SaveChangesAsync();
return Results.Ok(todos);
});
Použijte testovací nástroj rozhraní API, jako HttpRepl je předání následujících dat do předchozího koncového bodu:
[
{
"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"
}
}
]
Následující kód vytvoří vazbu na klíč X-Todo-Id záhlaví a vrátí Todo položky s odpovídajícími Id hodnotami:
// 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
Když vytvoříte vazbu string[] z řetězce dotazu, absence odpovídající hodnoty řetězce dotazu bude mít místo hodnoty null prázdné pole.
Vazba parametrů pro seznamy argumentů s [AsParameters]
AsParametersAttribute umožňuje jednoduchou vazbu parametrů na typy, nikoli komplexní nebo rekurzivní vazbu modelu.
Uvažujte následující kód:
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.
Zvažte následující GET koncový bod:
app.MapGet("/todoitems/{id}",
async (int Id, TodoDb Db) =>
await Db.Todos.FindAsync(Id)
is Todo todo
? Results.Ok(new TodoItemDTO(todo))
: Results.NotFound());
K nahrazení předchozích zvýrazněných parametrů můžete použít následující struct :
struct TodoItemRequest
{
public int Id { get; set; }
public TodoDb Db { get; set; }
}
Refaktorovaný GET koncový bod používá předchozí struct s atributem AsParameters :
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());
Následující kód ukazuje další koncové body v aplikaci:
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();
});
K refaktoringu seznamů parametrů se používají následující třídy:
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!;
}
Následující kód ukazuje refaktorované koncové body používající AsParameters a předchozí struct a třídy:
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();
});
K nahrazení předchozích parametrů je možné použít následující record typy:
record TodoItemRequest(int Id, TodoDb Db);
record CreateTodoItemRequest(TodoItemDTO Dto, TodoDb Db);
record EditTodoItemRequest(int Id, TodoItemDTO Dto, TodoDb Db);
Použití funkce with structAsParameters může být výkonnější než použití record typu.
Kompletní ukázkový kód v úložišti AspNetCore.Docs.Samples .
Vlastní vazba
Vazby parametrů můžete přizpůsobit třemi způsoby:
- Pro zdroje vazeb tras, dotazů a hlaviček vytvořte vazbu vlastních typů přidáním statické
TryParsemetody pro tento typ. - Proces vazby můžete řídit implementací
BindAsyncmetody typu. - V případě pokročilých scénářů implementujte IBindableFromHttpContext<TSelf> rozhraní tak, aby poskytovalo vlastní logiku vazby přímo z objektu
HttpContext.
TryParse
TryParse má dvě rozhraní API:
public static bool TryParse(string value, out T result);
public static bool TryParse(string value, IFormatProvider provider, out T result);
Následující kód se zobrazí Point: 12.3, 10.1 s identifikátorem URI /map?Point=12.3,10.1:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// GET /map?Point=12.3,10.1
app.MapGet("/map", (Point point) => $"Point: {point.X}, {point.Y}");
app.Run();
public class Point
{
public double X { get; set; }
public double Y { get; set; }
public static bool TryParse(string? value, IFormatProvider? provider,
out Point? point)
{
// Format is "(12.3,10.1)"
var trimmedValue = value?.TrimStart('(').TrimEnd(')');
var segments = trimmedValue?.Split(',',
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (segments?.Length == 2
&& double.TryParse(segments[0], out var x)
&& double.TryParse(segments[1], out var y))
{
point = new Point { X = x, Y = y };
return true;
}
point = null;
return false;
}
}
BindAsync
BindAsync má následující rozhraní API:
public static ValueTask<T?> BindAsync(HttpContext context, ParameterInfo parameter);
public static ValueTask<T?> BindAsync(HttpContext context);
Následující kód se zobrazí SortBy:xyz, SortDirection:Desc, CurrentPage:99 s identifikátorem URI /products?SortBy=xyz&SortDir=Desc&Page=99:
using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// GET /products?SortBy=xyz&SortDir=Desc&Page=99
app.MapGet("/products", (PagingData pageData) => $"SortBy:{pageData.SortBy}, " +
$"SortDirection:{pageData.SortDirection}, CurrentPage:{pageData.CurrentPage}");
app.Run();
public class PagingData
{
public string? SortBy { get; init; }
public SortDirection SortDirection { get; init; }
public int CurrentPage { get; init; } = 1;
public static ValueTask<PagingData?> BindAsync(HttpContext context,
ParameterInfo parameter)
{
const string sortByKey = "sortBy";
const string sortDirectionKey = "sortDir";
const string currentPageKey = "page";
Enum.TryParse<SortDirection>(context.Request.Query[sortDirectionKey],
ignoreCase: true, out var sortDirection);
int.TryParse(context.Request.Query[currentPageKey], out var page);
page = page == 0 ? 1 : page;
var result = new PagingData
{
SortBy = context.Request.Query[sortByKey],
SortDirection = sortDirection,
CurrentPage = page
};
return ValueTask.FromResult<PagingData?>(result);
}
}
public enum SortDirection
{
Default,
Asc,
Desc
}
Vlastní vazba parametrů s využitím IBindableFromHttpContext
ASP.NET Core poskytuje podporu pro vlastní vazbu parametrů v Minimal API pomocí IBindableFromHttpContext<TSelf> rozhraní. Rozhraní, které bylo představeno s použitím statických abstraktních členů v jazyce C# 11, umožňuje vytvářet typy, jež lze vázat na kontext HTTP přímo v parametrech obslužné rutiny trasy.
public interface IBindableFromHttpContext<TSelf>
where TSelf : class, IBindableFromHttpContext<TSelf>
{
static abstract ValueTask<TSelf?> BindAsync(HttpContext context, ParameterInfo parameter);
}
Implementací IBindableFromHttpContext<TSelf> rozhraní můžete vytvořit vlastní typy, které zpracovávají vlastní logiku vazby z HttpContext. Pokud obslužná rutina trasy obsahuje parametr tohoto typu, architektura automaticky volá statickou metodu BindAsync k vytvoření instance:
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}";
});
Následuje příklad implementace vlastního parametru, který vytvoří vazbu z hlavičky HTTP:
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
});
}
}
Můžete také implementovat ověřování v rámci vlastní logiky vazby:
app.MapGet("/validated", (ValidatedParameter param) =>
{
if (string.IsNullOrEmpty(param.Value))
{
return Results.BadRequest("Value cannot be empty");
}
return Results.Ok($"Validated value: {param.Value}");
});
Zobrazení nebo stažení ukázkového kódu (postup stažení)
Selhání vazeb
Pokud vazba selže, architektura zaznamená ladicí zprávu a v závislosti na režimu selhání vrátí klientovi různé stavové kódy.
| Režim selhání | Typ parametru s možnou hodnotou null | Zdroj vazby | Stavový kód |
|---|---|---|---|
{ParameterType}.TryParse návraty false |
yes | route/query/header | 400 |
{ParameterType}.BindAsync návraty null |
yes | custom | 400 |
{ParameterType}.BindAsync hází |
nezáleží na tom, | custom | 500 |
| Selhání deserializace textu JSON | nezáleží na tom, | body | 400 |
Nesprávný typ obsahu (ne application/json) |
nezáleží na tom, | body | 415 |
Priorita vazby
Pravidla pro určení zdroje vazby z parametru:
- Explicitní atribut definovaný u atributů parametru (From*) v následujícím pořadí:
- Hodnoty tras:
[FromRoute] - Řetězec dotazu:
[FromQuery] - Záhlaví:
[FromHeader] - Tělo:
[FromBody] - Služba:
[FromServices] - Hodnoty parametrů:
[AsParameters]
- Hodnoty tras:
- Speciální typy
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)
- Typ parametru má platnou statickou
BindAsyncmetodu. - Typ parametru je řetězec nebo má platnou statickou
TryParsemetodu.- Pokud název parametru existuje v šabloně trasy. V
app.Map("/todo/{id}", (int id) => {});,idje vázána z trasy. - Vázáno z řetězce dotazu.
- Pokud název parametru existuje v šabloně trasy. V
- Pokud je typ parametru služba poskytovaná injektáží závislostí, použije tuto službu jako zdroj.
- Parametr je z těla.
Konfigurace možností deserializace JSON pro vazbu textu
Zdroj vazby těla používá System.Text.Json k deserializaci. Toto výchozí nastavení není možné změnit, ale je možné nakonfigurovat serializaci JSON a možnosti deserializace.
Globální konfigurace možností deserializace JSON
Možnosti, které platí globálně pro aplikaci, je možné nakonfigurovat vyvoláním ConfigureHttpJsonOptions. Následující příklad obsahuje veřejná pole a formátuje výstup JSON.
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
// }
Vzhledem k tomu, že vzorový kód konfiguruje serializaci i deserializaci, může číst NameField a zahrnout NameField do výstupního kódu JSON.
Konfigurace možností deserializace JSON pro koncový bod
ReadFromJsonAsync má přetížení, které přijímají JsonSerializerOptions objekt. Následující příklad obsahuje veřejná pole a formátuje výstup JSON.
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
// }
Vzhledem k tomu, že předchozí kód aplikuje přizpůsobené možnosti pouze na deserializaci, výstupní JSON vylučuje NameField.
Čtení textu požadavku
Text požadavku si můžete přečíst přímo pomocí parametru nebo parametru HttpContextHttpRequest :
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();
Předchozí kód:
- Přistupuje k textu požadavku pomocí HttpRequest.BodyReader.
- Zkopíruje text požadavku do místního souboru.
Responses
Obslužné rutiny tras podporují následující typy návratových hodnot:
-
IResultna základě – to zahrnujeTask<IResult>aValueTask<IResult> -
string- To zahrnujeTask<string>aValueTask<string> -
T(Jakýkoli jiný typ) – to zahrnujeTask<T>aValueTask<T>
| Návratová hodnota | Behavior | Content-Type |
|---|---|---|
IResult |
Architektura volá IResult.ExecuteAsync. | Rozhodlo se implementací IResult |
string |
Architektura zapíše řetězec přímo do odpovědi. | text/plain |
T (Jakýkoli jiný typ) |
Rozhraní JSON serializuje odpověď. | application/json |
Podrobnější průvodce směrováním vrácených hodnot obslužné rutiny najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Příklad návratových hodnot
řetězcové návratové hodnoty
app.MapGet("/hello", () => "Hello World");
Návratové hodnoty JSON
app.MapGet("/hello", () => new { Message = "Hello World" });
Vrácení TypedResults
Následující kód vrátí TypedResults:
app.MapGet("/hello", () => TypedResults.Ok(new Message() { Text = "Hello World!" }));
TypedResults Vrácení je upřednostňované pro vrácení Results. Další informace naleznete v tématu TypedResults vs Výsledky.
Návratové hodnoty IResult
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Následující příklad používá předdefinované typy výsledků k přizpůsobení odpovědi:
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" }));
Vlastní stavový kó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");
});
Další příklady najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Redirect
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
File
app.MapGet("/download", () => Results.File("myfile.text"));
Předdefinované výsledky
Běžné pomocné rutiny výsledků existují ve statických ResultsTypedResults třídách.
TypedResults Vrácení je upřednostňované pro vrácení Results. Další informace naleznete v tématu TypedResults vs Výsledky.
Přizpůsobení výsledků
Aplikace můžou řídit odpovědi implementací vlastního IResult typu. Následující kód je příkladem typu výsledku HTML:
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);
}
}
Doporučujeme přidat metodu rozšíření, aby Microsoft.AspNetCore.Http.IResultExtensions byly tyto vlastní výsledky lépe zjistitelné.
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();
Zadané výsledky
Rozhraní IResult může představovat hodnoty vrácené z minimálních rozhraní API, která nevyužívají implicitní podporu pro serializaci JSON vráceného objektu do odpovědi HTTP.
Static Results třída slouží k vytvoření různých IResult objektů, které představují různé typy odpovědí. Můžete například nastavit stavový kód odpovědi nebo přesměrovat na jinou adresu URL.
Implementované IResult typy jsou veřejné, což umožňuje při testování kontrolní výrazy typů. Například:
[TestClass()]
public class WeatherApiTests
{
[TestMethod()]
public void MapWeatherApiTest()
{
var result = WeatherApi.GetAllWeathers();
Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
}
}
Můžete se podívat na návratové typy odpovídajících metod ve statické TypedResults třídy najít správný veřejný IResult typ, na který se má přetypovat.
Další příklady najdete v tématu Vytváření odpovědí v aplikacích s minimálním rozhraním API.
Filters
Zobrazení filtrů v minimálních aplikacích API
Authorization
Trasy je možné chránit pomocí zásad autorizace. Tyto můžou být deklarovány prostřednictvím atributu [Authorize] nebo pomocí RequireAuthorization metody:
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();
Předchozí kód lze napsat takto RequireAuthorization:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Následující ukázka používá autorizaci založenou na zásadách:
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();
Povolit neověřeným uživatelům přístup ke koncovému bodu
Umožňuje [AllowAnonymous] neověřeným uživatelům přístup ke koncovým bodům:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Trasy můžou být povolené CORS pomocí zásad CORS. CORS lze deklarovat prostřednictvím atributu [EnableCors] nebo pomocí RequireCors metody. Následující ukázky umožňují 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("/",() => "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();
Další informace najdete v tématu Povolení žádostí mezi zdroji (CORS) v ASP.NET Core
Viz také
Tento dokument:
- Poskytuje stručný přehled minimálních rozhraní API.
- Je určený pro zkušené vývojáře. Úvod najdete v tématu Kurz: Vytvoření minimálního rozhraní API s ASP.NET Core
Minimální rozhraní API se skládají z:
- WebApplication a WebApplicationBuilder
- Obslužné rutiny tras
WebApplication
Následující kód je generován šablonou ASP.NET Core:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Předchozí kód lze vytvořit prostřednictvím dotnet new web příkazového řádku nebo výběrem prázdné webové šablony v sadě Visual Studio.
Následující kód vytvoří WebApplication (app) bez explicitního vytvoření WebApplicationBuilder:
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run();
WebApplication.Create inicializuje novou instanci WebApplication třídy s předkonfigurovanými výchozími nastaveními.
Práce s porty
Při vytvoření webové aplikace pomocí sady Visual Studio nebo dotnet newProperties/launchSettings.json se vytvoří soubor, který určuje porty, na které aplikace reaguje. V ukázkách nastavení portů, které následují, vrátí spuštění aplikace ze sady Visual Studio dialogové okno Unable to connect to web server 'AppName's chybou . Z příkazového řádku spusťte následující ukázky změn portů.
Následující části nastavují port, na který aplikace reaguje.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.Run("http://localhost:3000");
V předchozím kódu aplikace reaguje na port 3000.
Více portů
V následujícím kódu aplikace reaguje na port 3000 a 4000.
var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:3000");
app.Urls.Add("http://localhost:4000");
app.MapGet("/", () => "Hello World");
app.Run();
Nastavení portu z příkazového řádku
Následující příkaz způsobí, že aplikace reaguje na port 7777:
dotnet run --urls="https://localhost:7777"
Kestrel Pokud je koncový bod také nakonfigurovaný v appsettings.json souboru, appsettings.json použije se zadaná adresa URL. Další informace najdete v tématu Kestrel Konfigurace koncového bodu.
Čtení portu z prostředí
Následující kód načte port z prostředí:
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello World");
app.Run($"http://localhost:{port}");
Upřednostňovaným způsobem nastavení portu z prostředí je použití ASPNETCORE_URLS proměnné prostředí, která je znázorněna v následující části.
Nastavení portů prostřednictvím proměnné prostředí ASPNETCORE_URLS
Proměnná ASPNETCORE_URLS prostředí je k dispozici pro nastavení portu:
ASPNETCORE_URLS=http://localhost:3000
ASPNETCORE_URLS podporuje více adres URL:
ASPNETCORE_URLS=http://localhost:3000;https://localhost:5000
Naslouchání na všech rozhraních
Následující ukázky ukazují naslouchání na všech rozhraních.
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();
Naslouchání všem rozhraním pomocí ASPNETCORE_URLS
Předchozí ukázky můžou použít ASPNETCORE_URLS
ASPNETCORE_URLS=http://*:3000;https://+:5000;http://0.0.0.0:5005
Zadání HTTPS s vývojovým certifikátem
var app = WebApplication.Create(args);
app.Urls.Add("https://localhost:3000");
app.MapGet("/", () => "Hello World");
app.Run();
Další informace o vývojovém certifikátu najdete v tématu Důvěryhodnost vývojového certifikátu ASP.NET Core HTTPS ve Windows a macOS.
Zadání HTTPS pomocí vlastního certifikátu
Následující části ukazují, jak zadat vlastní certifikát pomocí appsettings.json souboru a prostřednictvím konfigurace.
Zadání vlastního certifikátu pomocí appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Certificates": {
"Default": {
"Path": "cert.pem",
"KeyPath": "key.pem"
}
}
}
}
Zadání vlastního certifikátu prostřednictvím konfigurace
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();
Použití rozhraní API pro certifikáty
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();
Čtení prostředí
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();
Další informace o používání prostředí najdete v tématu runtime prostředí ASP.NET Core.
Configuration
Následující kód čte z konfiguračního systému:
var app = WebApplication.Create(args);
var message = app.Configuration["HelloKey"] ?? "Hello";
app.MapGet("/", () => message);
app.Run();
Další informace najdete v tématu Konfigurace v ASP.NET Core
Logging
Následující kód zapíše zprávu do protokolu při spuštění aplikace:
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => "Hello World");
app.Run();
Další informace najdete v tématu Protokolování v .NET a ASP.NET Core
Přístup ke kontejneru injektáže závislostí (DI)
Následující kód ukazuje, jak získat služby z kontejneru DI během spouštění aplikace:
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();
Další informace naleznete v tématu Injektáž závislostí v ASP.NET Core.
WebApplicationBuilder
Tato část obsahuje vzorový kód používající WebApplicationBuilder.
Změna kořenového adresáře obsahu, názvu aplikace a prostředí
Následující kód nastaví kořen obsahu, název aplikace a prostředí:
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 inicializuje novou instanci třídy WebApplicationBuilder s předkonfigurovanými výchozími hodnotami.
Další informace najdete v tématu ASP.NET Základní základní přehled
Změna kořenového adresáře obsahu, názvu aplikace a prostředí podle proměnných prostředí nebo příkazového řádku
Následující tabulka ukazuje proměnnou prostředí a argument příkazového řádku použitý ke změně kořenového adresáře obsahu, názvu aplikace a prostředí:
| atribut | Proměnná prostředí | Argument příkazového řádku |
|---|---|---|
| Název aplikace | ASPNETCORE_APPLICATIONNAME | --applicationName |
| Název prostředí | ASPNETCORE_ENVIRONMENT | --environment |
| Kořenový adresář obsahu | ASPNETCORE_CONTENTROOT | --contentRoot |
Přidání zprostředkovatelů konfigurace
Následující ukázka přidá zprostředkovatele konfigurace INI:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddIniFile("appsettings.ini");
var app = builder.Build();
Podrobné informace najdete v tématu Zprostředkovatelé konfigurace souborů v části Konfigurace v ASP.NET Core.
Konfigurace čtení
Ve výchozím nastavení WebApplicationBuilder konfigurace čtení z více zdrojů, včetně:
-
appSettings.jsonaappSettings.{environment}.json - Proměnné prostředí
- Příkazový řádek
Úplný seznam přečtených zdrojů konfigurace najdete v tématu Výchozí konfigurace v konfiguraci v ASP.NET Core.
Následující kód načte HelloKey z konfigurace a zobrazí hodnotu v koncovém / bodu. Pokud má konfigurační hodnota hodnotu null, je "Hello" přiřazeno k message:
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
Čtení prostředí
var builder = WebApplication.CreateBuilder(args);
var message = builder.Configuration["HelloKey"] ?? "Hello";
var app = builder.Build();
app.MapGet("/", () => message);
app.Run();
Přidání zprostředkovatelů protokolování
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();
Přidání služeb
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();
Přizpůsobení nástroje IHostBuilder
K existujícím metodám IHostBuilder rozšíření lze přistupovat pomocí vlastnosti Host:
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();
Přizpůsobení IWebHostBuilderu
Metody rozšíření lze IWebHostBuilder získat přístup pomocí WebApplicationBuilder.WebHost vlastnost.
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();
Změna webového kořenového adresáře
Ve výchozím nastavení je kořenový adresář webu relativní ke kořenovému wwwroot adresáři obsahu ve složce. Webový kořenový adresář je místo, kde middleware statického souboru hledá statické soubory. Kořenový adresář webu lze změnit pomocí WebHostOptionspříkazového řádku nebo pomocí UseWebRoot metody:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in webroot
WebRootPath = "webroot"
});
var app = builder.Build();
app.Run();
Kontejner injektáže vlastních závislostí (DI)
Následující příklad používá autofac:
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();
Přidání middlewaru
Jakýkoli existující middleware ASP.NET Core je možné nakonfigurovat na :WebApplication
var app = WebApplication.Create(args);
// Setup the file server to serve static files.
app.UseFileServer();
app.MapGet("/", () => "Hello World!");
app.Run();
Další informace najdete v tématu ASP.NET Core Middleware
Stránka výjimky pro vývojáře
WebApplication.CreateBuilder inicializuje novou instanci WebApplicationBuilder třídy s předkonfigurovanými výchozími nastaveními. Stránka výjimky vývojáře je povolená v předkonfigurovaných výchozích nastaveních. Když se ve vývojovém prostředí spustí následující kód, přejdete k / vykreslení popisné stránky, která zobrazí výjimku.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () =>
{
throw new InvalidOperationException("Oops, the '/' route has thrown an exception.");
});
app.Run();
Middleware ASP.NET Core
Následující tabulka uvádí některé z middlewarů, které se často používají s minimálními rozhraními API.
| Middleware | Description | API |
|---|---|---|
| Authentication | Poskytuje podporu ověřování. | UseAuthentication |
| Authorization | Poskytuje podporu autorizace. | UseAuthorization |
| CORS | Konfiguruje sdílení prostředků mezi zdroji (CORS). | UseCors |
| Obslužná rutina výjimky | Globálně zpracovává výjimky vyvolané kanálem middlewaru. | UseExceptionHandler |
| Přeposílané hlavičky | Předá přeposílané hlavičky do aktuálního požadavku. | UseForwardedHeaders |
| Přesměrování HTTPS | Přesměruje všechny požadavky HTTP na HTTPS. | UseHttpsRedirection |
| Zabezpečení striktního přenosu HTTP (HSTS) | Middleware pro vylepšení zabezpečení, který přidává speciální hlavičku odpovědi. | UseHsts |
| Protokolování požadavku | Poskytuje podporu protokolování požadavků a odpovědí HTTP. | UseHttpLogging |
| Protokolování požadavků W3C | Poskytuje podporu pro protokolování požadavků HTTP a odpovědí ve formátu W3C. | UseW3CLogging |
| Ukládání odpovědí do mezipaměti | Poskytuje podporu pro ukládání odpovědí do mezipaměti. | UseResponseCaching |
| Komprese odpovědí | Poskytuje podporu pro kompresi odpovědí. | UseResponseCompression |
| Session | Poskytuje podporu pro správu uživatelských relací. | UseSession |
| Statické soubory | Poskytuje podporu pro obsluhu statických souborů a procházení adresářů. | UseStaticFiles, UseFileServer |
| WebSockets | Povoluje protokol WebSocket. | UseWebSockets |
Zpracování žádostí
Následující části se týkají směrování, vazby parametrů a odpovědí.
Routing
Nakonfigurovaná WebApplication podpora Map{Verb} a 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();
Obslužné rutiny tras
Obslužné rutiny tras jsou metody, které se spouštějí, když se trasa shoduje. Obslužné rutiny tras můžou být funkcí libovolného obrazce, včetně synchronního nebo asynchronního. Obslužné rutiny tras mohou být výraz lambda, místní funkce, metoda instance nebo statická metoda.
Výraz lambda
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();
Místní funkce
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Metoda instance
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";
}
}
Statická metoda
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";
}
}
Pojmenované koncové body a generování propojení
Koncové body můžou mít názvy, aby se vygenerovaly adresy URL koncového bodu. Použitím pojmenovaného koncového bodu se v aplikaci nemusíte pevně zakódovat cesty:
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();
Předchozí kód se zobrazí The link to the hello endpoint is /hello z koncového / bodu.
POZNÁMKA: V názvech koncových bodů se rozlišují malá a velká písmena.
Názvy koncových bodů:
- Musí být globálně jedinečný.
- Používají se jako ID operace OpenAPI, pokud je povolená podpora OpenAPI. Další informace najdete v tématu OpenAPI.
Parametry trasy
Parametry trasy je možné zachytit jako součást definice vzoru trasy:
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();
Předchozí kód vrátí The user id is 3 and book id is 7 z identifikátoru URI /users/3/books/7.
Obslužná rutina trasy může deklarovat parametry, které se mají zachytit. Když je požadavek proveden trasu s parametry deklarovanými k zachycení, parametry se analyzují a předávají obslužné rutině. To usnadňuje zachytávání hodnot v bezpečném typu. V předchozím kódu userId a bookId jsou oba int.
Pokud v předchozím kódu nelze převést intna některou hodnotu trasy , vyvolá se výjimka. Požadavek /users/hello/books/3 GET vyvolá následující výjimku:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Zástupný znak a zachycení všech tras
Následující zachytávání všech návratových tras Routing to hello z koncového bodu /posts/hello:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Omezení trasy
Omezení trasy omezují odpovídající chování trasy.
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();
Následující tabulka ukazuje předchozí šablony tras a jejich chování:
| Šablona trasy | Příklad odpovídajícího identifikátoru URI |
|---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
Další informace najdete v tématu Referenční informace o omezení trasy ve směrování v ASP.NET Core.
Vazba parametru
Vazba parametru je proces převodu dat požadavku na parametry silného typu, které jsou vyjádřeny obslužnými rutinami tras. Zdroj vazby určuje, odkud jsou parametry vázány. Zdroje vazeb můžou být explicitní nebo odvozené na základě metody HTTP a typu parametru.
Podporované zdroje vazeb:
- Hodnoty tras
- Řetězec dotazu
- Header
- Text (jako JSON)
- Služby poskytované injektáží závislostí
- Custom
Note
Vazba z hodnot formulářů není nativně podporována v .NET.
Následující příklad obslužné rutiny trasy GET používá některé z těchto zdrojů vazeb parametrů:
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 { }
Následující tabulka ukazuje vztah mezi parametry použitými v předchozím příkladu a přidruženými zdroji vazeb.
| Parameter | Zdroj vazby |
|---|---|
id |
hodnota trasy |
page |
řetězec dotazu |
customHeader |
hlavička |
service |
Poskytuje injektáž závislostí |
Metody GETHTTP , HEAD, OPTIONSa DELETE nejsou implicitně vázány z těla. Pokud chcete vytvořit vazbu z textu (jako JSON) pro tyto metody HTTP, vytvořte vazbu explicitně s [FromBody] použitím nebo čtením z objektu HttpRequest.
Následující příklad obslužné rutiny trasy POST používá pro parametr zdroj vazby těla (jako JSON):person
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/", (Person person) => { });
record Person(string Name, int Age);
Parametry v předchozích příkladech jsou všechny vázány z dat požadavku automaticky. Abychom si ukázali pohodlí, které poskytuje vazba parametrů, následující ukázkové obslužné rutiny tras ukazují, jak číst data požadavku přímo z požadavku:
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>();
// ...
});
Explicitní vazba parametru
Atributy lze použít k explicitní deklaraci, kde jsou parametry vázány.
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 | Zdroj vazby |
|---|---|
id |
hodnota trasy s názvem id |
page |
řetězec dotazu s názvem "p" |
service |
Poskytuje injektáž závislostí |
contentType |
hlavička s názvem "Content-Type" |
Note
Vazba z hodnot formulářů není nativně podporována v .NET.
Vazba parametru s DI
Vazba parametrů pro minimální rozhraní API vytvoří vazbu parametrů prostřednictvím injektáže závislostí, když je typ nakonfigurovaný jako služba. Atribut není nutné explicitně použít [FromServices] u parametru. V následujícím kódu vrátí obě akce čas:
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();
Volitelné parametry
Parametry deklarované v obslužných rutinách tras se považují za povinné:
- Pokud požadavek odpovídá trase, obslužná rutina trasy se spustí pouze v případě, že jsou v požadavku zadány všechny požadované parametry.
- Při zadání všech požadovaných parametrů dojde k chybě.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int pageNumber) => $"Requesting page {pageNumber}");
app.Run();
| identifikátor URI | result |
|---|---|
/products?pageNumber=3 |
Vráceno 3 |
/products |
BadHttpRequestException: Požadovaný parametr int pageNumber nebyl z řetězce dotazu zadaný. |
/products/1 |
Chyba HTTP 404, žádná odpovídající trasa |
Pokud chcete nastavit pageNumber jako volitelný, definujte typ jako volitelný nebo zadejte výchozí hodnotu:
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();
| identifikátor URI | result |
|---|---|
/products?pageNumber=3 |
Vráceno 3 |
/products |
1 vráceno |
/products2 |
1 vráceno |
Předchozí hodnota s možnou hodnotou null a výchozí hodnotou platí pro všechny zdroje:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/products", (Product? product) => { });
app.Run();
Předchozí kód volá metodu s produktem null, pokud není odeslán žádný text požadavku.
POZNÁMKA: Pokud jsou zadána neplatná data a parametr má hodnotu null, obslužná rutina trasy se nespustí .
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products", (int? pageNumber) => $"Requesting page {pageNumber ?? 1}");
app.Run();
| identifikátor URI | result |
|---|---|
/products?pageNumber=3 |
3 vrácený |
/products |
1 vrácený |
/products?pageNumber=two |
BadHttpRequestException: Nepodařilo se vytvořit vazbu parametru "Nullable<int> pageNumber" ze dvou. |
/products/two |
Chyba HTTP 404, žádná odpovídající trasa |
Další informace najdete v části Selhání vazeb.
Speciální typy
Následující typy jsou vázané bez explicitních atributů:
HttpContext: Kontext, který obsahuje všechny informace o aktuálním požadavku HTTP nebo odpovědi:
app.MapGet("/", (HttpContext context) => context.Response.WriteAsync("Hello World"));HttpRequest a HttpResponse: Požadavek HTTP a odpověď HTTP:
app.MapGet("/", (HttpRequest request, HttpResponse response) => response.WriteAsync($"Hello World {request.Query["name"]}"));CancellationToken: Token zrušení přidružený k aktuálnímu požadavku HTTP:
app.MapGet("/", async (CancellationToken cancellationToken) => await MakeLongRunningRequestAsync(cancellationToken));ClaimsPrincipal: Uživatel přidružený k požadavku vázanému z HttpContext.User:
app.MapGet("/", (ClaimsPrincipal user) => user.Identity.Name);
Vlastní vazba
Vazby parametrů můžete přizpůsobit dvěma způsoby:
- Pro zdroje vazeb tras, dotazů a hlaviček vytvořte vazbu vlastních typů přidáním statické
TryParsemetody pro tento typ. - Proces vazby můžete řídit implementací
BindAsyncmetody typu.
TryParse
TryParse má dvě rozhraní API:
public static bool TryParse(string value, out T result);
public static bool TryParse(string value, IFormatProvider provider, out T result);
Následující kód se zobrazí Point: 12.3, 10.1 s identifikátorem URI /map?Point=12.3,10.1:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// GET /map?Point=12.3,10.1
app.MapGet("/map", (Point point) => $"Point: {point.X}, {point.Y}");
app.Run();
public class Point
{
public double X { get; set; }
public double Y { get; set; }
public static bool TryParse(string? value, IFormatProvider? provider,
out Point? point)
{
// Format is "(12.3,10.1)"
var trimmedValue = value?.TrimStart('(').TrimEnd(')');
var segments = trimmedValue?.Split(',',
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (segments?.Length == 2
&& double.TryParse(segments[0], out var x)
&& double.TryParse(segments[1], out var y))
{
point = new Point { X = x, Y = y };
return true;
}
point = null;
return false;
}
}
BindAsync
BindAsync má následující rozhraní API:
public static ValueTask<T?> BindAsync(HttpContext context, ParameterInfo parameter);
public static ValueTask<T?> BindAsync(HttpContext context);
Následující kód se zobrazí SortBy:xyz, SortDirection:Desc, CurrentPage:99 s identifikátorem URI /products?SortBy=xyz&SortDir=Desc&Page=99:
using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// GET /products?SortBy=xyz&SortDir=Desc&Page=99
app.MapGet("/products", (PagingData pageData) => $"SortBy:{pageData.SortBy}, " +
$"SortDirection:{pageData.SortDirection}, CurrentPage:{pageData.CurrentPage}");
app.Run();
public class PagingData
{
public string? SortBy { get; init; }
public SortDirection SortDirection { get; init; }
public int CurrentPage { get; init; } = 1;
public static ValueTask<PagingData?> BindAsync(HttpContext context,
ParameterInfo parameter)
{
const string sortByKey = "sortBy";
const string sortDirectionKey = "sortDir";
const string currentPageKey = "page";
Enum.TryParse<SortDirection>(context.Request.Query[sortDirectionKey],
ignoreCase: true, out var sortDirection);
int.TryParse(context.Request.Query[currentPageKey], out var page);
page = page == 0 ? 1 : page;
var result = new PagingData
{
SortBy = context.Request.Query[sortByKey],
SortDirection = sortDirection,
CurrentPage = page
};
return ValueTask.FromResult<PagingData?>(result);
}
}
public enum SortDirection
{
Default,
Asc,
Desc
}
Selhání vazeb
Pokud vazba selže, architektura zaznamená ladicí zprávu a v závislosti na režimu selhání vrátí klientovi různé stavové kódy.
| Režim selhání | Typ parametru s možnou hodnotou null | Zdroj vazby | Stavový kód |
|---|---|---|---|
{ParameterType}.TryParse návraty false |
yes | route/query/header | 400 |
{ParameterType}.BindAsync návraty null |
yes | custom | 400 |
{ParameterType}.BindAsync hází |
nezáleží na tom, | custom | 500 |
| Selhání deserializace textu JSON | nezáleží na tom, | body | 400 |
Nesprávný typ obsahu (ne application/json) |
nezáleží na tom, | body | 415 |
Priorita vazby
Pravidla pro určení zdroje vazby z parametru:
- Explicitní atribut definovaný u atributů parametru (From*) v následujícím pořadí:
- Hodnoty tras:
[FromRoute] - Řetězec dotazu:
[FromQuery] - Záhlaví:
[FromHeader] - Tělo:
[FromBody] - Služba:
[FromServices]
- Hodnoty tras:
- Speciální typy
- Typ parametru má platnou
BindAsyncmetodu. - Typ parametru je řetězec nebo má platnou
TryParsemetodu.- Pokud název parametru existuje v šabloně trasy. V
app.Map("/todo/{id}", (int id) => {});,idje vázána z trasy. - Vázáno z řetězce dotazu.
- Pokud název parametru existuje v šabloně trasy. V
- Pokud je typ parametru služba poskytovaná injektáží závislostí, použije tuto službu jako zdroj.
- Parametr je z těla.
Přizpůsobení vazby JSON
Zdroj vazby těla se používá System.Text.Json k de-serializaci. Toto výchozí nastavení není možné změnit, ale vazbu je možné přizpůsobit pomocí jiných technik popsaných výše. Pokud chcete přizpůsobit možnosti serializátoru JSON, použijte kód podobný následujícímu:
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;
}
Předchozí kód:
- Nakonfiguruje výchozí možnosti JSON pro vstup i výstup.
- Vrátí následující kód JSON.
Při publikování{ "id": 1, "name": "Joe Smith" }{ "Id": 1, "Name": "Joe Smith" }
Čtení textu požadavku
Text požadavku si můžete přečíst přímo pomocí parametru nebo parametru HttpContextHttpRequest :
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();
Předchozí kód:
- Přistupuje k textu požadavku pomocí HttpRequest.BodyReader.
- Zkopíruje text požadavku do místního souboru.
Responses
Obslužné rutiny tras podporují následující typy návratových hodnot:
-
IResultna základě – to zahrnujeTask<IResult>aValueTask<IResult> -
string- To zahrnujeTask<string>aValueTask<string> -
T(Jakýkoli jiný typ) – to zahrnujeTask<T>aValueTask<T>
| Návratová hodnota | Behavior | Content-Type |
|---|---|---|
IResult |
Architektura volá IResult.ExecuteAsync. | Rozhodlo se implementací IResult |
string |
Architektura zapíše řetězec přímo do odpovědi. | text/plain |
T (Jakýkoli jiný typ) |
Architektura bude serializovat odpověď JSON. | application/json |
Příklad návratových hodnot
řetězcové návratové hodnoty
app.MapGet("/hello", () => "Hello World");
Návratové hodnoty JSON
app.MapGet("/hello", () => new { Message = "Hello World" });
Návratové hodnoty IResult
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
Následující příklad používá předdefinované typy výsledků k přizpůsobení odpovědi:
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" }));
Vlastní stavový kó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"));
Předdefinované výsledky
Běžné pomocné rutiny výsledků existují ve Microsoft.AspNetCore.Http.Results statické třídě.
| Description | Typ odpovědi | Stavový kód | API |
|---|---|---|---|
| Napsání odpovědi JSON s pokročilými možnostmi | application/json | 200 | Results.Json |
| Napsání odpovědi JSON | application/json | 200 | Results.Ok |
| Napsání textové odpovědi | text/prostý (výchozí), konfigurovatelný | 200 | Results.Text |
| Zápis odpovědi jako bajtů | application/octet-stream (výchozí), konfigurovatelné | 200 | Results.Bytes |
| Zápis datového proudu bajtů do odpovědi | application/octet-stream (výchozí), konfigurovatelné | 200 | Results.Stream |
| Streamování souboru do odpovědi ke stažení pomocí hlavičky content-disposition | application/octet-stream (výchozí), konfigurovatelné | 200 | Results.File |
| Nastavte stavový kód na 404 s volitelnou odpovědí JSON. | N/A | 404 | Results.NotFound |
| Nastavení stavového kódu na 204 | N/A | 204 | Results.NoContent |
| Nastavte stavový kód na 422 s volitelnou odpovědí JSON. | N/A | 422 | Results.UnprocessableEntity |
| Nastavte stavový kód na 400 s volitelnou odpovědí JSON. | N/A | 400 | Results.BadRequest |
| Nastavte stavový kód na 409 s volitelnou odpovědí JSON. | N/A | 409 | Results.Conflict |
| Napsání objektu JSON s podrobnostmi o problému do odpovědi | N/A | 500 (výchozí), konfigurovatelné | Results.Problem |
| Napsání objektu JSON s podrobnostmi o problému do odpovědi s chybami ověření | N/A | Není k dispozici, konfigurovatelné | Results.ValidationProblem |
Přizpůsobení výsledků
Aplikace můžou řídit odpovědi implementací vlastního IResult typu. Následující kód je příkladem typu výsledku HTML:
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);
}
}
Doporučujeme přidat metodu rozšíření, aby Microsoft.AspNetCore.Http.IResultExtensions byly tyto vlastní výsledky lépe zjistitelné.
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
Trasy je možné chránit pomocí zásad autorizace. Tyto můžou být deklarovány prostřednictvím atributu [Authorize] nebo pomocí RequireAuthorization metody:
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();
Předchozí kód lze napsat takto RequireAuthorization:
app.MapGet("/auth", () => "This endpoint requires authorization")
.RequireAuthorization();
Následující ukázka používá autorizaci založenou na zásadách:
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();
Povolit neověřeným uživatelům přístup ke koncovému bodu
Umožňuje [AllowAnonymous] neověřeným uživatelům přístup ke koncovým bodům:
app.MapGet("/login", [AllowAnonymous] () => "This endpoint is for all roles.");
app.MapGet("/login2", () => "This endpoint also for all roles.")
.AllowAnonymous();
CORS
Trasy můžou být povolené CORS pomocí zásad CORS. CORS lze deklarovat prostřednictvím atributu [EnableCors] nebo pomocí RequireCors metody. Následující ukázky umožňují 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("/",() => "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();
Další informace najdete v tématu Povolení žádostí mezi zdroji (CORS) v ASP.NET Core