URL参数编码及Request.QueryString遇到“+”时的情况

今天突然遇到个默名奇妙的现象,参数"id=25"始终无法解析 :

此前参数传递方式都是:
客户端:
  //先通过DES加密,再用Encode编码。
  <%# URL.Encode(DES.Encode(Eval("Id").ToString(), DES.SECRET)) %>
服务器:
  //先通过DES解密,再用Decode编码。
  int.TryParse(URL.Decode(DES.Decode(Request.QueryString["id"], DES.SECRET)), out hotelId);
PS:URL和DES都是封装的类,直接调用的静态方法。
单步调试了一下,原来"25"经过加密编码后返回的字符串为:"gkn+7QsXyP8=" 再通过EnCode编码参数就变成了:"gkn%2b7QsXyP8%3d"
这里面有个很特别的字符"+"!因为,在url中+表示空格,通过Reflector工具调试到UrlDecode内部方法可以很容易的看出这一点,页面底部是调试得来的代码,红色部分写的很清楚。
此时查看QueryString 可以看到: Request.QueryString = {id=gkn+7QsXyP8%3d}
执行:Request.QueryString["id"].ToString()后得到的值却是:"gkn 7QsXyP8="。可以看出+变成了空格,%3d变成了= 。
找到了问题的原因,下面就是解决办法了:Request.QueryString["id"].RePlace(" ","+")。
 
此外:在url中如果出现特殊字符会有一套处理的规则:使用"%+ASCII值"的形式来替代原字符。
例如:+ 转换为%2d 、= 转换为%3d 、? 转换为%3f。值得注意的就是在url中+表示空格
附:UrlDecode反编译后的代码,看得出+的特殊性 
private static string UrlDecodeStringFromStringInternal(string s, Encoding e)
{
    int length = s.Length;
    UrlDecoder decoder = new UrlDecoder(length, e);
    for (int i = 0; i < length; i++)
    {
        char ch = s[i];
        //注意这里
        if (ch == '+')
        {
            ch = ' ';
        }
        else if ((ch == '%') && (i < (length - 2)))
        {
            if ((s[i + 1] == 'u') && (i < (length - 5)))
            {
                int num3 = HexToInt(s[i + 2]);
                int num4 = HexToInt(s[i + 3]);
                int num5 = HexToInt(s[i + 4]);
                int num6 = HexToInt(s[i + 5]);
                if (((num3 < 0) || (num4 < 0)) || ((num5 < 0) || (num6 < 0)))
                {
                    goto Label_0106;
                }
                ch = (char) ((((num3 << 12) | (num4 << 8)) | (num5 << 4)) | num6);
                i += 5;
                decoder.AddChar(ch);
                continue;
            }
            int num7 = HexToInt(s[i + 1]);
            int num8 = HexToInt(s[i + 2]);
            if ((num7 >= 0) && (num8 >= 0))
            {
                byte b = (byte) ((num7 << 4) | num8);
                i += 2;
                decoder.AddByte(b);
                continue;
            }
        }
    Label_0106:
        if ((ch & 0xff80) == 0)
        {
            decoder.AddByte((byte) ch);
        }
        else
        {
            decoder.AddChar(ch);
        }
    }
    return decoder.GetString();
}
原文地址:https://www.cnblogs.com/wadeheng/p/1920936.html