复制的NameValueCollection的ToString()不会输出所需的结果

时间:2013-11-01 09:21:48

标签: c# asp.net

我在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()方法输出所需的结果?

3 个答案:

答案 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