我正在尝试编写一个控制器操作,它将获取给定 URL 的元数据(具体来说,要传递哪些参数)。还有很多类似的问题,例如Asp.Net core get RouteData value from url,但从 ASP.NET Core 3.1 开始这些问题似乎不正确,因为它已切换到“端点路由”。
因此,类似的代码var router = RouteData.Routers.First(); //get the top level router将不再正常工作,因为Routers没有填充任何有意义的内容。
我看到了一些使用当前HttpContext 端点的示例,例如此处,但没有一个用于自定义端点。
我也看到过提及IActionDescriptorCollectionProvider,但这不会让我轻松过滤特定的 URL。
到目前为止,我正在注入一个 HttpContextFactory,但从IEndpointFeature当前上下文传递它:
private readonly IHttpContextFactory _HttpContextFactory;
public MyController(IHttpContextFact httpContextFactory)
{
_HttpContextFactory = httpContextFactory;
}
public async Task<ActionResult> GetRouteDataForUrl([FromQuery(Name = "url")] string url)
{
var uri = new Uri(url);
// this is probably wrong -- it supplies the _original_ context's endpoint feature
var featureCollection = this.HttpContext.Features;
var httpContext = _HttpContextFactory.Create(featureCollection);
httpContext.Request.Path = uri.PathAndQuery;
var feature = httpContext.Features.Get<IEndpointFeature>();
var endpoint = httpContext.Features.Get<IEndpointFeature>()?.Endpoint; // see https://github.com/aspnet/AspNetCore/issues/5135#issuecomment-461547335
return Ok(endpoint.Metadata.OfType<Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor>());
}
Run Code Online (Sandbox Code Playgroud)
这可以让我得到正确的类型,但不能得到正确的结果。
没有公共构造函数EndpointFeature,所以我可能不应该传递我自己的构造函数。上面的代码从原始(“错误”)http 上下文中获取IEndpointFeature,因此将为我提供GetRouteDataForUrl控制器的端点,而不是我在 URL 中传递的控制器的端点。
我最终解决了这个问题(尽管我不确定我是以最干净或最有效的方式这样做的)。
我最终使用的两个关键部分是 anEndpointDataSource和 a LinkParser:
private readonly EndpointDataSource _EndpointDataSource;
private readonly LinkParser _LinkParser;
public MyController(EndpointDataSource endpointDataSource, LinkParser linkParser)
{
_EndpointDataSource = endpointDataSource;
_LinkParser = linkParser;
}
Run Code Online (Sandbox Code Playgroud)
我可以使用端点数据源来迭代所有端点,并使用链接解析器来匹配端点expectedUri(这是用户传递的 URL):
[HttpGet]
public IActionResult GetActionMetadata(Uri forUri)
{
foreach (var endpoint in this._EndpointDataSource.Endpoints)
{
if (!TryGetEndpointMetadata(endpoint, out var name, out var controllerActionDescriptor))
continue;
// we only use this to match the endpoint to the URL
var dict = _LinkParser.ParsePathByEndpointName(name, expectedUri.AbsolutePath);
if (dict == null)
continue;
// if we get here, it's the endpoint we're looking for, and we can proceed with your actual parsing
/* actually do things with the endpoint */
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5174 次 |
| 最近记录: |