Obslužné rutiny tras v minimálních aplikacích API
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v tématu .NET a .NET Core Zásady podpory. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Nakonfigurovaná podpora a kde je metoda HTTP typu Pascal cased, například Get
, Put
Post
nebo Delete
:{Verb}
MapMethods Map{Verb}
WebApplication
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();
Instanční metoda
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.cs
umí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 int
na 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 QueryPrivateTodos
pro 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 parametrů v aplikacích s minimálním rozhraním API podrobně popisuje pravidla pro naplnění parametrů obslužné rutiny trasy.
Odpovědi
Vytváření odpovědí v aplikacích s minimálním rozhraním API podrobně popisuje, jak se hodnoty vrácené z obslužných rutin tras převedou na odpovědi.