我在usercontrol中有一个NameValueCollection
,其初始化如下:
private NameValueCollection _nameValues = HttpUtility.ParseQueryString(Request.QueryString.ToString());
当我在此调用ToString()
时,它会生成一个正确的查询字符串,我可以将其用于更新的网址。
但是,当我通过其构造函数复制NameValueCollection
时,如下所示:
var nameValues = new NameValueCollection(_nameValues);
然后尝试形成一个网址:
var newUrl = String.Concat(_rootPath + "?" + nameValues.ToString());
输出这样的网址:
“http://www.domain.com?System.Collections.Specialized.NameValueCollection”
如何复制NameValueCollection
以便ToString()
方法输出所需的结果?
答案 0 :(得分:15)
问题是代码中有两种实际类型。第一个是System.Web.HttpValueCollection,它使用ToString方法覆盖以获得您期望的结果,第二个是System.Collection.Specialized.NameValueCollection,它不会覆盖ToString。你可以做什么,如果你真的需要使用System.Collection.Specialized.NameValueCollection就是创建一个扩展方法。
public static string ToQueryString(this NameValueCollection collection)
{
var array = (from key in collection.AllKeys
from value in collection.GetValues(key)
select string.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value))).ToArray();
return "?" + string.Join("&", array);
}
并使用它:
var newUrl = String.Concat(_rootPath,nameValues.ToQueryString());
答案 1 :(得分:3)
提供字符串格式的不是NameValueCollection
。该功能位于System.Web.HttpValueCollection
返回的内部类HttpUtility.ParseQueryString
中。
因此,您将无法通过使用内置功能来实现此行为。您最好的选择是创建一种扩展方法,以URL格式格式化值。
以下是来自HttpValueCollection
类的方法 - 您可以通过一些修改来使用它。
// System.Web.HttpValueCollection
internal virtual string ToString(bool urlencoded, IDictionary excludeKeys)
{
int count = this.Count;
if (count == 0)
{
return string.Empty;
}
StringBuilder stringBuilder = new StringBuilder();
bool flag = excludeKeys != null && excludeKeys["__VIEWSTATE"] != null;
for (int i = 0; i < count; i++)
{
string text = this.GetKey(i);
if ((!flag || text == null || !text.StartsWith("__VIEWSTATE", StringComparison.Ordinal)) && (excludeKeys == null || text == null || excludeKeys[text] == null))
{
if (urlencoded)
{
text = HttpValueCollection.UrlEncodeForToString(text);
}
string value = (text != null) ? (text + "=") : string.Empty;
string[] values = this.GetValues(i);
if (stringBuilder.Length > 0)
{
stringBuilder.Append('&');
}
if (values == null || values.Length == 0)
{
stringBuilder.Append(value);
}
else
{
if (values.Length == 1)
{
stringBuilder.Append(value);
string text2 = values[0];
if (urlencoded)
{
text2 = HttpValueCollection.UrlEncodeForToString(text2);
}
stringBuilder.Append(text2);
}
else
{
for (int j = 0; j < values.Length; j++)
{
if (j > 0)
{
stringBuilder.Append('&');
}
stringBuilder.Append(value);
string text2 = values[j];
if (urlencoded)
{
text2 = HttpValueCollection.UrlEncodeForToString(text2);
}
stringBuilder.Append(text2);
}
}
}
}
}
return stringBuilder.ToString();
}
internal static string UrlEncodeForToString(string input)
{
return HttpUtility.UrlEncodeUnicode(input);
}
答案 2 :(得分:1)
在名称值集合上调用.ToString()
将只为您提供它所属的命名空间。
我怀疑你想要它的关键和价值,假设它是收藏中的第一个,为什么不做呢:
var newUrl = String.Concat(_rootPath + "?" + nameValues.GetKey(0) + nameValues.Get(0));
您可以将此作为扩展方法:
public static string ToString(this NameValueCollection nvc, int idx)
{
if(nvc == null)
throw new NullReferenceException();
string key = nvc[idx];
if(nvc.HasKeys() && !string.IsNullOrEmpty(key))
{
return string.Concat(key, nvc.Get(key)); //maybe want some formatting here
}
return string.Empty;
}
用法:
NameValueCollection nvc = new NameValueCollection();
string foo = nvc.ToString(0); //gets key + value at index 0