ASP.NET 核心 Request.Query 对比 Request.Path

ASP.NET Core Request.Query vs Request.Path

我有以下代码,它使用策略要求来查看用户是否有权访问特定的 matchKey。这是我的控制器操作

    [HttpGet]
    [Authorize(Policy = Policy.Match)]
    public async Task<IActionResult> Index(Guid matchKey)
    {
        var model = await _mediator.Send(new MatchIndexQuery
        {
            MatchKey = matchKey
        });

        return View("Index", model);
    }

我从 request.query 中获取了 matchKey,一切正常。

     protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MatchRequirement requirement)
    {
        if (context.Resource is HttpContext httpContext)
        {
            var query = httpContext.Request.Query;

            if (query.TryGetValue("matchKey", out StringValues matchKeyString))
            {
                if (Guid.TryParse(matchKeyString.ToString(), out Guid matchKey))
                {
                     // Do some checks here and return
                     context.Succeed(requirement);
                }
            }
         }
    }

一切正常,现在我想让我的 URL 更好一点,这样我就可以使用 /Match/{matchKey} 而不是 /Match?matchKey={matchKey} 这样我就有了以下路线。

    [HttpGet]
    [Authorize(Policy = Policy.Match)]
    [Route("[controller]/{matchKey?}")]
    [Route("[controller]/[action]/{matchKey?}")]
    public async Task<IActionResult> Index(Guid matchKey)
    {
        var model = await _mediator.Send(new MatchIndexQuery
        {
            MatchKey = matchKey
        });

        return View("Index", model);
    }

但是现在我的策略不起作用,因为 {matchKey} 不再出现在 Request.Query 中,而是作为 Request.Path 的一部分。

是否有任何统一的方法可以在我的政策中获取 {matchKey},或者如果我在查询中找不到它,我是否需要根据 Request.Path 进行一些字符串拆分?

or do I need to some some string splitting based on the Request.Path if I can't find it in the query?

是的,你可以拆分httpContext.Request.Path并得到matchKey的值。

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MatchRequirement requirement)
    {
        if (context.Resource is HttpContext httpContext)
        {
            var path = httpContext.Request.Path.ToString().Split("/");
            //if Path contains matchKey,httpContext.Request.Path.ToString() will be /controllername/actionname/matchkeyvalue,and the length of path will be 4
            if (path.Length==4)
            {
                var matchKeyString=path[path.Length - 1];
                if (Guid.TryParse(matchKeyString.ToString(), out Guid matchKey))
                {
                     // Do some checks here and return
                     context.Succeed(requirement);
                }
            }
         }
    }