通过路由模板获取标记化路径匹配(ASP.NET Core 3.1)

时间:2020-03-15 14:13:47

标签: c# asp.net-core

我正在尝试找出最佳方法,以获取与路由模板匹配的原始请求URI的片段,即https://apim.example.com/api/v1/controller/[a/{id}/b],其中[..]是片段与路由模板匹配;路径可以从this.Request.Path获得,但是片段是否可以单独获得?

我已阅读(全部)文档,检查了HttpRequest实例的所有属性,但未找到实际的标记化片段(仅描述控制器/动作参数(如命名等)的元数据)。我需要将该片段作为代理API的一部分(具有特定于模式的处理程序)。

代理API

我正在ASP.NET Core 3.1(位于Azure API Management实例后面)编写代理服务,该服务映射远程API的子集并在顶部应用安全性方案。代理识别出一组已知的路由签名,以便根据请求的资源来应用安全方案。

已发送到Azure API管理的请求(例如):

https://apim.example.com/api/v1/organizations/{id}/{*path}

Azure API管理转发的请求代理:

https://proxy.example.com/api/v1/proxy/v1/organizations/{id}/{*path}

值得一提的是,代理和远程API均提供了一个个性化的版本控制方案(因此来自Azure API Management的完全限定的代理路径)。从以下代码段可以看出,该代理是通过ASP.NET Core 3.1 routing实现的:

[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class ProxyController : ControllerBase
{
    .. constructors and other members omitted for brevity

    [HttpGet]
    [HttpPost]
    [HttpPut]
    [HttpDelete]
    [Route("v1/organizations/{id:int}/{*path}")]
    public async Task OrganizationsAsync(int organizationID, string path, CancellationToken cancellation = default)
    {
        // would like to get the tokenized "v1/organizations/{id:int}/{*path}" fragment here

        var message = await this.service.HandleAsync(this.Request, path, cancellation);

        await this.handler.CopyAsync(this.HttpContext, message);
    }
}

OrganizationsAsync中,我正在寻找一种动态方法来获取v1/organizations/{id:int}/{*path}片段,而不必预先定义控制器的各种基本URI(如以下示例所示)。 / p>

使用预定义的控制器URI

[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class ProxyController : ControllerBase
{
    .. constructors and other members omitted for brevity

    private readonly string baseUri = "api/v1/proxy";

    [HttpGet]
    [HttpPost]
    [HttpPut]
    [HttpDelete]
    [Route("v1/organizations/{id:int}/{*path}")]
    public async Task OrganizationsAsync(int organizationID, string path, CancellationToken cancellation = default)
    {
        var localpath = this.Request.Path.Value.Replace(this.baseUri, "");
        var message = await this.service.HandleAsync(this.Request, localpath, cancellation);

        await this.handler.CopyAsync(this.HttpContext, message);
    }
}

1 个答案:

答案 0 :(得分:1)

根据ASP.NET Core团队,目前没有API提供仅匹配路由模板签名的字符串片段(或等效结构)。

我决定从路由值中创建片段,如以下代码片段所示:

[ApiController]
[ApiVersion("1.0")]
[Route("api/v{apiVersion:apiVersion}/[controller]")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class ProxyController : ControllerBase
{
    .. constructors and other members omitted for brevity

    [HttpGet]
    [HttpPost]
    [HttpPut]
    [HttpDelete]
    [Authorize]
    [Route("v{version:int}/organizations/{organizationID:int}/{*path}")]
    public async Task OrganizationsAsync(int version, int organizationID, string path, CancellationToken cancellation = default)
    {
        await this.HandleAsync($"v{version}/organizations/{organizationID}/{path}", cancellation);
    }
}