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

C# 为什么我的查询字符串参数被url解码两次?,c#,.net,asp.net-web-api,urldecode,C#,.net,Asp.net Web Api,Urldecode,我有一个使用.NET4.7.1的WebAPI,在其中一个端点上执行get时,我注意到一些奇怪的行为。当我执行到达端点http://localhost:52684/api/v1/some-资源?客户端时区=%2B0500参数客户端时区作为“0500”而不是“+0500”接收。我能想到的唯一一件事是Url被解码了两次,所以%2B”变成“+”,然后变成“。有人知道这种情况的常见原因吗?或者为什么会发生这种情况 控制器上有一个类似的端点 [HttpGet] [Authorize] [ApiRoute("

我有一个使用.NET4.7.1的WebAPI,在其中一个端点上执行get时,我注意到一些奇怪的行为。当我执行到达端点
http://localhost:52684/api/v1/some-资源?客户端时区=%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();
}

我想我找到了原因。我创建了一个
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);
    }
}
公共类SnakeCaseActionSelector:ApiControllerActionSelector
{
公共覆盖HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
var requestUri=controllerContext.Request.requestUri;
var queryPairs=controllerContext.Request.GetQueryNameValuePairs().ToList();
如果(!queryPairs.Any())
{
返回base.SelectAction(controllerContext);
}
queryPairs=queryPairs.Select(x=>
新的键值对(camelcasetosnakecasecaseconverter.FromSnakeCase(x.Key),x.Value))
.ToList();
var newQueryParams=queryPairs.Select(x=>$“{x.Key}={x.Value}”).Aggregate((x,y)=>x+”&+y);
var builder=新的UriBuilder(requestUri)
{
Query=newQueryParams
};
controllerContext.Request.RequestUri=builder.Uri;
返回base.SelectAction(controllerContext);
}
}

您的代码中有这样的例子吗?你能发布那个代码吗?我相信+被解释为一个空格。如果你用谷歌搜索“a b c”,查询将变为“”,看看空格是如何变为加号的。是的,但我将+编码为%2。它不是重复的。我明确声明我在查询字符串中使用了%2B,结果变成了一个空格。那篇帖子说我正在做的是在查询字符串中使用%2B而不是+。我确实认为它是重复的,因为Web API对查询字符串和编码的
+
字符没有问题。很可能您在编写的某个自定义筛选器中进行双重解码。