为什么我的查询字符串参数被url解码两次?

时间:2018-08-13 19:12:55

标签: c# .net asp.net-web-api urldecode

我有一个使用.Net 4.7.1的Web api,在其中一个端点上执行get操作时,我注意到一些奇怪的行为。当我执行到端点http://localhost:52684/api/v1/some-resource?client_timezone=%2B0500的获取时,参数客户端时区将以" 0500"而不是"+0500"的形式接收。我唯一能想到的是Url被解码了两次,因此"%2B"变成了"+",然后变成了" "。有谁知道这的任何常见原因或为什么会发生?

这是控制器上的类似端点

[HttpGet]
[Authorize]
[ApiRoute("some-resource", StartingVersion = 1)]
[EnableCors("*", "*", "GET", "*")]
public IHttpActionResult SomeResource([FromUri] string timezone)
{
    if (!DataValidationUtililties.IsValidClientTimezone(timezone))
    {
        return BadRequest();
    }
    return Ok();
}

1 个答案:

答案 0 :(得分:1)

我想我找到了原因。我创建了一个SnakeCaseActionSelector,它实际上重写了所有请求URI。这样,它会解码url,而不会再次对查询字符串参数进行编码。

public class SnakeCaseActionSelector : ApiControllerActionSelector
{
    public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
    {
        var requestUri = controllerContext.Request.RequestUri;
        var queryPairs = controllerContext.Request.GetQueryNameValuePairs().ToList();
        if (!queryPairs.Any())
        {
            return base.SelectAction(controllerContext);
        }
        queryPairs = queryPairs.Select(x =>
                new KeyValuePair<string, string>(CamelCaseToSnakeCaseConverter.FromSnakeCase(x.Key), x.Value))
            .ToList();
        var newQueryParams = queryPairs.Select(x => $"{x.Key}={x.Value}").Aggregate((x, y) => x + "&" + y);
        var builder = new UriBuilder(requestUri)
        {
            Query = newQueryParams
        };
        controllerContext.Request.RequestUri = builder.Uri;

        return base.SelectAction(controllerContext);
    }
}