获取不同 HttpContext 的 Endpoint

Sör*_*lau 5 c# asp.net-core

我正在尝试编写一个控制器操作,它将获取给定 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 中传递的控制器的端点。

Sör*_*lau 0

我最终解决了这个问题(尽管我不确定我是以最干净或最有效的方式这样做的)。

我最终使用的两个关键部分是 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)