【问题标题】:ToString() of copied NameValueCollection doesn't output desired results复制的 NameValueCollection 的 ToString() 未输出所需的结果
【发布时间】:2013-11-12 11:40:56
【问题描述】:

我在一个用户控件中有一个NameValueCollection,它的初始化如下:

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

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

但是,当我像这样通过其构造函数复制 NameValueCollection 时:

var nameValues = new NameValueCollection(_nameValues);

然后尝试形成一个url:

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

它会输出一个这样的 url:

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

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

【问题讨论】:

标签: c# asp.net


【解决方案1】:

提供字符串格式的不是NameValueCollection。该功能位于 HttpUtility.ParseQueryString 返回的内部类 System.Web.HttpValueCollection 中。

因此,您将无法通过使用内置功能来实现此行为。最好的办法是创建一个扩展方法,将值格式化为 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】:

    在名称值集合上调用 .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
    

    【讨论】:

      【解决方案3】:

      问题是您的代码中有两种实际类型。第一个是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());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-26
        • 2012-10-22
        • 2015-03-04
        • 2013-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多