15

我有一个NameValueCollection像这样初始化的用户控件:

private NameValueCollection _nameValues = HttpUtility.ParseQueryString(Request.QueryString.ToString());

当我调用ToString()它时,它会生成一个正确的查询字符串,我可以将其用于更新的 url。

但是,当我NameValueCollection通过它的构造函数复制时,如下所示:

var nameValues = new NameValueCollection(_nameValues);

然后尝试形成一个url:

var newUrl = String.Concat(_rootPath + "?" + nameValues.ToString());

它输出一个这样的网址:

http://www.domain.com?System.Collections.Specialized.NameValueCollection

如何复制 aNameValueCollection以便该ToString()方法输出所需的结果?

4

3 回答 3

22

问题是您的代码中有两种实际类型。第一个是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());
于 2013-11-01T09:43:27.743 回答
3

它不是NameValueCollection提供字符串格式的。该功能位于System.Web.HttpValueCollectionHttpUtility.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);
}
于 2013-11-01T09:28:33.893 回答
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
于 2013-11-01T09:29:13.470 回答