Search code examples
asp.net-coreroutesasp.net-authorization

ASP.NET Core Request.Query vs Request.Path


I have the following code which using a policy requirement to see if a user has access to a specific matchKey. Here is my controller action

    [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);
    }

I get the matchKey from the request.query and everything works as intended.

     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);
                }
            }
         }
    }

This all works, now I'd like to make my URL a bit nicer so I can just have /Match/{matchKey} instead of /Match?matchKey={matchKey} so I have the following route.

    [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);
    }

However now my policy doesn't work because the {matchKey} isn't seen in the Request.Query anymore but as part of the Request.Path.

Is there any unified way to get the {matchKey} in my policy or do I need to some some string splitting based on the Request.Path if I can't find it in the query?


Solution

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

    Yes,you can split httpContext.Request.Path and get the value of 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);
                    }
                }
             }
        }