我正在运行一个 .net 8.0 asp.net 最小 API 应用程序,该应用程序部署在各个位置,每个位置都有不同的前面的请求 URL。例如我的搜索控制器:
[ApiController]
[Route("[controller]")]
public class SearchController : ControllerBase {
[HttpGet] public async Task<ActionResult<SomeValue[]>> Search([FromQuery] string query) { ... }
}
可以使用以下任何示例字符串来触发:
/search?query=term
/api/search?query=term
/some/multi/part/prefix/search?query=term
我试图找到一种方法来只考虑最后一部分,例如
[Route([*/controller])]
,但不幸的是,无法使用 Route
属性来完成它。
所以我尝试做一些动态请求操作,比如:
app.Use(async (context, next) => {
context.Request.Path = "/search";
var request = context.Request.Path.Value;
var i = request.LastIndexOf('/');
context.Request.Path = request[..i];
await next();
});
但是,尽管见证了
context.Request.Path
确实发生了变化,但路由本身似乎并未受到影响。
所以我尝试了
app.MapDynamicControllerRoute<Router>("{**path}")
并被迫(为了测试):
public class Router : DynamicRouteValueTransformer {
public override ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values) {
httpContext.Request.Path = "/search";
values["path"] = "search";
return new(values);
}
}
再说一次:
httpContext.Request.Path
和values["path"]
都反映了变化,但实际的路由没有改变,控制器也没有被击中。
那么我错过了什么?有什么办法可以完成这个动态路由吗?
我发现我的案例与实际工作解决方案没有完全匹配,并且无法使
app.MapDynamicControllerRoute<Router>("{**path}")
更改实际路由。
您可以尝试在中间件之后显式添加
app.UseRouting();
。
app.Use(async (context, next) => {
//if the path contains "search", then change it all to "search"
if (context.Request.Path.Value.Contains("/search"))
{
context.Request.Path = "/search";
}
await next();
});
app.UseRouting();