在 System.Web 命名空间 下有个静态方法:
HttpUtility.ParseQueryString (String, Encoding)
使用指定的 Encoding 将查询字符串分析成一个 NameValueCollection。
我们如下代码显示的是我们需要的东西:
string query = "?searchtype=1&bigclassid=0&searchKeys=123+456&author=&tabletype=now";
NameValueCollection nv = HttpUtility.ParseQueryString(query);
Console.WriteLine(nv["tabletype"]);
但是我们用 Reflector 去看这个函数的实现:
其中调用到了 System.Web.HttpValueCollection 类的
internal void FillFromString(
string s,
bool urlencoded,
Encoding encoding); 方法
从 Reflector 看这个函数的实现如下:
internal void FillFromString(string s, bool urlencoded, Encoding encoding)
{
int num1 = (s != null) ? s.Length : 0;
for (int num2 = 0; num2 < num1; num2++)
{
int num3 = num2;
int num4 = -1;
while (num2 < num1)
{
switch (s[num2])
{
case '=':
if (num4 < 0)
{
num4 = num2;
}
break;
}
num2++;
}
string text1 = null;
string text2 = null;
if (num4 >= 0)
{
text1 = s.Substring(num3, num4 - num3);
text2 = s.Substring(num4 + 1, (num2 - num4) - 1);
}
else
{
text2 = s.Substring(num3, num2 - num3);
}
if (urlencoded)
{
base.Add(HttpUtility.UrlDecode(text1, encoding), HttpUtility.UrlDecode(text2, encoding));
}
else
{
base.Add(text1, text2);
}
if ((num2 == (num1 - 1)) && (s[num2] == '&'))
{
base.Add(null, string.Empty);
}
}
}
|
分析代码我们就可以知道:它没有处理参数中,多个参数的问题。
如果我们把这个代码复制出来执行,它是无法把?searchtype=1&bigclassid=0&searchKeys=123+456&author=&tabletype=now 这样QueryString 中的后面几个参数解析出来的。
怪异的问题就在这里,
执行出来的效果是分析出来了,而分析代码却没有分析出来。
这个问题,也有其他人看到:
比如:http://codebetter.com/blogs/karlseguin/archive/2006/05/04/144052.aspx
不过他提供的解析函数,忽略考虑了一种情况:如果参数中出现如下的情况就会报错
from=/Expert/search.asp?bigclassid=61
所以我在用他的函数时候,对他的一个函数作了修改:
public static NameValueCollection ParseQueryString(string query, char delimiter)
{
if (delimiter == '\0')
{
throw new ArgumentNullException("delimiter");
}
NameValueCollection queryString = new NameValueCollection();
if (query == null || query.Length == 0)
{
return queryString;
}
if (query.StartsWith("?"))
{
query = query.Substring(1, query.Length - 1);
}
string[] pairs = query.Split(delimiter);
foreach (string pair in pairs)
{
int tt = pair.IndexOf('=');
if (tt <= 0)
continue;
string name = null, val = null;
name = pair.Substring(0, tt);
if (pair.Length > tt)
val = pair.Substring(tt + 1);
queryString.Add(name, val);
}
return queryString;
}
至于 Reflector 分析出来的代码,经过请教几个牛人,最后认为是 Reflector 分析代码出错误了。出错就在 switch 函数那里,
1、 其中的 case '=': 的break 是退出 switch 而不是退出循环
2、 估计其中少了一个 case '&'
请教 装配脑袋 后,觉得正确地分析出来的代码应该是:
internal void FillFromString(string s, bool urlencoded, Encoding encoding)
{
int num1 = (s != null) ? s.Length : 0;
for (int num2 = 0; num2 < num1; num2++)
{
int num3 = num2;
int num4 = -1;
while (num2 < num1)
{
switch (s[num2])
{
case '=':
if (num4 < 0)
{
num4 = num2;
}
break;
case '&':
goto BREAKWHILE;
}
num2++;
}
BREAKWHILE:
string text1 = null;
string text2 = null;
if (num4 >= 0)
{
text1 = s.Substring(num3, num4 - num3);
text2 = s.Substring(num4 + 1, (num2 - num4) - 1);
}
else
{
text2 = s.Substring(num3, num2 - num3);
}
if (urlencoded)
{
base.Add(HttpUtility.UrlDecode(text1, encoding), HttpUtility.UrlDecode(text2, encoding));
}
else
{
base.Add(text1, text2);
}
if ((num2 == (num1 - 1)) && (s[num2] == '&'))
{
base.Add(null, string.Empty);
}
}
}