在ASP中使用RouteGroupBuilder时如何获取路由组前缀?. NET Core 7 WebApi



.NET v7框架引入了路由组的概念,根据路径中的公共前缀将映射的端点分组在一起:

app.MapGroup("/public/todos").MapTodosApi();

现在,为了返回Created响应(即POST请求)的绝对路径,我需要在服务中使用该路由路径前缀。这个用例甚至在官方文档中有讨论:

在201 Created结果中不使用Location头的相对地址,还可以使用GroupRouteBuilder。GroupPrefix用于构造根相对地址

但是,GroupRouteBuilder类不存在。只有一个RouteGroupBuilder,但是它的实例没有成员GroupPrefix。有什么建议如何得到前缀吗?

你链接的文档-尽管是预览文档-提到:

使用GetPathByRouteValuesGetUriByRouteValuesrouteName有更多的选择。

关于链接生成的官方版本在这里。
它展示了如何注入和使用LinkGenerator (也包含上面提到的两个方法)和这样一个命名路由。

可以为端点指定名称,以便生成指向端点的url。使用命名端点可以避免在应用程序中硬编码路径

要将此应用到您所引用的示例中,
为检索Todo项的路由命名,并在生成creatatedat url时使用它。


var group = app.MapGroup("todos");
group
.MapGet("/{id}", (int id) =>
{                
// ...
return new Todo { Id = id };
})
.WithName("GetToDo");
group
.MapPost("/", (Todo todo, LinkGenerator linkGenerator) =>
{
// ...
var url = linkGenerator.GetPathByName("GetToDo", new { id = todo.Id });
return TypedResults.Created(url, todo);
});

在组合created-at url时使用组前缀的想法在GET (GET -item)端点的模式有一个额外的段的情况下是不够的,因为那个将不包括在内。您最终将组合多个硬编码字符串部分。

如果上面示例中的get-todo-item端点有一个额外的extra段(如下例所示),那么id为123ToDo项的创建地址url必须为

/todos/extra/123

linkGenerator与命名路由结合使用可以解决这个问题。

group
.MapGet("/extra/{id}", (int id) =>
{                
// ...
return new Todo { Id = id };
})
.WithName("GetToDo");

我删除了我的另一个答案,因为它只显示了您提到的完整路由模式。我能够通过检查EndpointDataSources获得前缀,并返回到RouteGroupBuilder(使用反射)。仍然不是很漂亮,但是如果你必须这样做,并且不想单独存储它,这可能是一个临时选项。

app.MapGroup("/public/todos").MapTodosApi();
app.Run();
public class Todo
{
public int Id { get; set; }
public string? Title { get; set; }
public bool IsComplete { get; set; }
}
public static class TodosApi
{
public static RouteGroupBuilder MapTodosApi(this RouteGroupBuilder group)
{
group.MapPost("/test", CreateTodo);
return group;
}
public static async Task<Created<Todo>> CreateTodo(Todo todo, IEnumerable<EndpointDataSource> endpointSources)
{
var compositeDataSource = (CompositeEndpointDataSource)(endpointSources.FirstOrDefault());
var datasource = compositeDataSource.DataSources.FirstOrDefault();
var nestedTypes = typeof(RouteGroupBuilder).GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance);
var routeGroupBuilderField = nestedTypes[0].GetField("_routeGroupBuilder", BindingFlags.NonPublic | BindingFlags.Instance);
var routeGroupValue = routeGroupBuilderField.GetValue(datasource);
var partialPrefixField = typeof(RouteGroupBuilder).GetField("_partialPrefix", BindingFlags.NonPublic | BindingFlags.Instance);

var partialPrefixValue = partialPrefixField.GetValue(routeGroupValue);

return TypedResults.Created($"{todo.Id}", todo);
}
}

partialPrefixValue返回"/public/todos",而不是完整的"/public/todos/test"_partialPrefixRouteGroupBuilder中的一个字段:https://github.com/dotnet/aspnetcore/blob/79e341268ac468cab6cfb09d6a1543103f66143c/src/Http/Routing/src/RouteGroupBuilder.cs

相关内容

  • 没有找到相关文章

最新更新