我正在尝试编写一个 Controller 操作,它将获取给定 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 使用端点的示例,例如 here ,但没有自定义的。
我还看到提到 IActionDescriptorCollectionProvider
,但这不会让我轻松过滤特定的 URL。
到目前为止,我正在注入(inject)一个 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>());
}
这可以让我得到正确的类型,但不是正确的结果。
EndpointFeature
没有公共(public)构造函数,所以我可能不应该通过我自己的。上面的代码采用 IEndpointFeature
来自原始(“错误”)http上下文,因此会给我一个GetRouteDataForUrl
的端点 Controller ,而不是我在 URL 中传递的 Controller 。
最佳答案
我最终解决了这个问题(尽管我不确定我是否以最干净或最有效的方式这样做)。
我最终使用的两个关键部分是 EndpointDataSource
和 LinkParser
:
private readonly EndpointDataSource _EndpointDataSource;
private readonly LinkParser _LinkParser;
public MyController(EndpointDataSource endpointDataSource, LinkParser linkParser)
{
_EndpointDataSource = endpointDataSource;
_LinkParser = linkParser;
}
我可以使用端点数据源遍历所有端点,并使用链接解析器将端点与
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 */
}
}
关于c# - 获取不同 HttpContext 的端点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59561114/