首页 > 解决方案 > 如何使 Webapi GET 方法与查询参数上的保留字符一起使用?

问题描述

我有一个非常简单的 web 服务,它带有一个带有令牌字符串参数的 GET 方法。我使用这个标记可以有字母,“+”和“/”。例如:mC1SW7RJhgsQGtRHhsg/Q+FGoZjbBleNKtpqT7zLMtE

如果有此令牌的数据,我使用此令牌在数据库中查找。

我在控制器中的方法是这样的:

[HttpGet("{token}")]
[ProducesResponseType(typeof(string), 200)]
[ProducesResponseType(typeof(void), 404)]
public JsonResult Get(string token)
{
    string sql = "SELECT dataObject FROM Session WHERE id = @SessionToken";
    var data = _conn.QueryFirstOrDefault<Session>(sql, new {SessionToken = token});
    if (data == null){
        var r = Json(string.Empty);
        r.StatusCode = StatusCodes.Status404NotFound;
        return r;
    }
    else {
        return Json(JsonConvert.DeserializeObject(data.dataObject));
    }
}

例如,我看到 Dapper/Webapi 自动转义此参数并将“/”更改为“%2F”。

当我部署它时,它只适用于没有特殊字符的令牌并返回 404。

作为一种解决方法,我更改了服务器中的令牌以对令牌进行编码并将编码的加号替换为空格:

string decodedToken = WebUtility.UrlDecode(token);
token = decodedToken.Replace(" ", "+");

问题是我需要我的客户做相反的事情并替换“+”号:

var encodedToken = WebUtility.UrlEncode(token);
// Convert '+' to ' '
token = encodedToken.Replace("%2B", " ");

在不要求客户更换 de '+' 符号的情况下,推荐的工作方式是什么?

标签: restasp.net-coreiisasp.net-core-webapi

解决方案


出于某种原因,Kestrel 或 .NET MVC 在编码的 URL 中进行部分解码。这看起来像一个 BUG ( https://github.com/aspnet/Mvc/issues/6388 ),但有一个解决方法。

使用您传递的令牌,您将在客户端对其进行编码:

 Original Token: mC1SW7RJhgsQGtRHhsg/Q+FGoZjbBleNKtpqT7zLMtE   
 Encoded Token: mC1SW7RJhgsQGtRHhsg%2FQ%2BFGoZjbBleNKtpqT7zLMtE

看到“/”变成了“%2F”,“+”变成了“%2B”。这是因为这两个字符是组成 URL 的一部分。因此,要将它们完全传递给 WebApi,必须将它们替换为它们的 ASCII 表示。

您将使用编码的令牌调用您的服务,如下所示:

 http://myserver:1234/myservice/token/mC1SW7RJhgsQGtRHhsg%2FQ%2BFGoZjbBleNKtpqT7zLMtE

在您的服务中,由于该错误,您将从 Kestrel/MVC 收到以下部分解码的字符串:

 Partially decoded token: mC1SW7RJhgsQGtRHhsg%2FQ+FGoZjbBleNKtpqT7zLMtE

只需实现一个简单的替换:

 token.Replace("%2F", "/");

您的字符串将被完全解码。


推荐阅读