Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 10 deste artigo.
Advertência
Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e do .NET Core. Para a versão atual, consulte a versão .NET 10 deste artigo.
Um WebApplication configurado suporta Map{Verb} e MapMethods onde {Verb} é um método HTTP com maiúsculas em Pascal, como Get, Post, Put ou Delete:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "This is a GET");
app.MapPost("/", () => "This is a POST");
app.MapPut("/", () => "This is a PUT");
app.MapDelete("/", () => "This is a DELETE");
app.MapMethods("/options-or-head", new[] { "OPTIONS", "HEAD" },
() => "This is an options or head request ");
app.Run();
Os Delegate argumentos passados para esses métodos são chamados de "manipuladores de rota".
Manipuladores de rotas
Os manipuladores de rota são métodos que são executados quando a rota corresponde. Os manipuladores de rota podem ser uma expressão lambda, uma função local, um método de instância ou um método estático. Os manipuladores de rota podem ser síncronos ou assíncronos.
Expressão 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();
Função local
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
string LocalFunction() => "This is local function";
app.MapGet("/", LocalFunction);
app.Run();
Método de instância
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";
}
}
Método estático
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";
}
}
Ponto final definido fora do Program.cs
As APIs mínimas não precisam estar localizadas em Program.cs.
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" });
});
}
}
Consulte também Grupos de rotas mais adiante neste artigo.
Pontos de extremidade nomeados e geração de hiperligações
Os pontos de extremidade podem receber nomes para gerar URLs para o ponto de extremidade. Usar um ponto de extremidade nomeado evita ter que codificar caminhos em um aplicativo:
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();
O código anterior mostra The link to the hello route is /hello a partir do ponto final /.
NOTA: Os nomes dos pontos finais são sensíveis a maiúsculas e minúsculas.
Nomes de pontos finais:
- Deve ser globalmente único.
- São usados como o id de operação OpenAPI quando o suporte OpenAPI está ativado. Para obter mais informações, consulte OpenAPI.
Parâmetros de rota
Os parâmetros de rota podem ser capturados como parte da definição do padrão de rota:
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();
O código anterior retorna The user id is 3 and book id is 7 do URI /users/3/books/7.
O manipulador de rotas pode declarar os parâmetros a serem capturados. Quando uma solicitação é feita para uma rota com parâmetros declarados para captura, os parâmetros são analisados e passados para o manipulador. Isso facilita a captura dos valores de forma segura. No código anterior, userId e bookId são int.
No código anterior, se qualquer valor de rota não puder ser convertido em um int, uma exceção será lançada. A solicitação GET /users/hello/books/3 lança a seguinte exceção:
BadHttpRequestException: Failed to bind parameter "int userId" from "hello".
Curinga e pegar todas as rotas
A seguinte rota abrangente retorna Routing to hello do endpoint '/posts/hello':
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/posts/{*rest}", (string rest) => $"Routing to {rest}");
app.Run();
Restrições de rota
As restrições de rota restringem o comportamento correspondente de uma rota.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/todos/{id:int}", (int id) => db.Todos.Find(id));
app.MapGet("/todos/{text}", (string text) => db.Todos.Where(t => t.Text.Contains(text));
app.MapGet("/posts/{slug:regex(^[a-z0-9_-]+$)}", (string slug) => $"Post {slug}");
app.Run();
A tabela a seguir demonstra os modelos de rota anteriores e seu comportamento:
| Modelo de rota | Exemplo de URI correspondente |
|---|---|
/todos/{id:int} |
/todos/1 |
/todos/{text} |
/todos/something |
/posts/{slug:regex(^[a-z0-9_-]+$)} |
/posts/mypost |
Para obter mais informações, consulte referência sobre restrições de rota no Roteamento no ASP.NET Core.
Grupos de rotas
O método de extensão MapGroup ajuda a organizar grupos de pontos de extremidade com um prefixo comum. Ele reduz o código repetitivo e permite personalizar grupos inteiros de endpoints com uma única chamada para métodos como RequireAuthorization e WithMetadata que adicionam metadados de endpoint .
Por exemplo, o código a seguir cria dois grupos semelhantes de pontos de extremidade:
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;
}
Nesse cenário, você pode usar um endereço relativo para o cabeçalho Location no resultado 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);
}
O primeiro grupo de endpoints só corresponderá a solicitações prefixadas com /public/todos e será acessível sem quaisquer autenticações. O segundo grupo de pontos de extremidade só corresponderá a solicitações prefixadas com /private/todos e exigirá autenticação.
A fábrica de filtros de ponto de extremidade QueryPrivateTodos é uma função local que modifica os parâmetros do manipulador de rotas TodoDb para permitir o acesso e o armazenamento de dados de tarefas privadas.
Os grupos de rotas também suportam grupos aninhados e padrões de prefixo complexos com parâmetros e restrições de rota. No exemplo a seguir, o manipulador de rotas mapeado para o grupo user pode capturar os parâmetros de rota {org} e {group} definidos nos prefixos do grupo externo.
O prefixo também pode estar vazio. Isso pode ser útil para adicionar metadados ou filtros de ponto de extremidade a um grupo de pontos de extremidade sem alterar o padrão de rota.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
Adicionar filtros ou metadados a um grupo comporta-se da mesma forma que adicioná-los individualmente a cada ponto de extremidade antes de adicionar quaisquer filtros ou metadados adicionais que possam ter sido adicionados a um grupo interno ou ponto de extremidade específico.
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);
});
No exemplo acima, o filtro externo registrará a solicitação de entrada antes do filtro interno, mesmo que ele tenha sido adicionado em segundo lugar. Como os filtros foram aplicados a grupos diferentes, a ordem em que foram adicionados em relação uns aos outros não importa. Os filtros de ordem adicionados são importantes se aplicados ao mesmo grupo ou ponto de extremidade específico.
Uma solicitação para /outer/inner/ registrará o seguinte:
/outer group filter
/inner group filter
MapGet filter
Vinculação de parâmetros
A vinculação de parâmetros em aplicativos de API mínima descreve as regras em detalhes de como os parâmetros do manipulador de rotas são preenchidos.
Respostas
Create responses in Minimal API applications descreve em detalhes como os valores retornados dos manipuladores de rotas são convertidos em respostas.