如何使用重复键构建WebClient查询字符串?

时间:2013-07-01 23:20:56

标签: c# duplicates query-string webclient

我将数据发布到一项服务,该服务要求我提交重复的查询字符串键(丑陋且未在任何标准中指定)。

我正在使用WebClient对象来构建请求。我想继续使用它,因为它经常在项目的其他地方使用。

当我这样做时

 foreach(var f in formats)                
      client.QueryString.Add("formats", f);

我收到服务不支持的列表&formats=format_1,format_2,format_3

有没有比这种老派丑陋更好的选择:

var extraQueryString = string.Empty;

extraQueryString += "?apiKey=" + TRANSCODE_KEY;
extraQueryString += "&fileKey=" + fileKey;

foreach (var f in formats)     
      extraQueryString += "&formats=" + f;

var response = client.UploadData(TRANSCODE_URI + "task" + extraQueryString , new byte[] { });

2 个答案:

答案 0 :(得分:1)

原因是NameValueCollection用逗号分隔重复键。您可以扩展NameValueCollection并覆盖Get方法,并让它返回您想要的格式。

public class DupeNVC: NameValueCollection
{
    private string _duplicateKey;
    public DupeNVC(string duplicateKey = null)
    {
        _duplicateKey = duplicateKey;
    }

    public override string Get(int index)
    {
        //check if duplicate key has been specified
        //if not, then call the default Get implementation
        if (!String.IsNullOrEmpty(_duplicateKey))
        {
            ArrayList list = (ArrayList)base.BaseGet(index);              

            int num = (list != null) ? list.Count : 0;
            if (num == 1)
            {
                return (string)list[0];
            }
            if (num > 1)
            {
                StringBuilder stringBuilder = new StringBuilder((string)list[0]);

                for (int i = 1; i < num; i++)
                {
                    //format our string and append the duplicate key specified
                    stringBuilder.AppendFormat("&{0}=", _duplicateKey);
                    stringBuilder.Append((string)list[i]);
                }
                return stringBuilder.ToString();                   
            }
            return null;
        }
        else
           return base.Get(index);
    }

} 

你可以像普通的NameValueCollection一样使用它,但是如果你在构造函数中传入一个重复的strning,它会查找该重复的键并运行上面的修改过的代码(否则它只会使用默认的{{ 1}}方法。

base.Get

这尚未经过全面测试,但应输出您想要的查询字符串格式。当然,这可以通过收集重复键来进一步扩展,但这只是为了让您了解当前的问题。

答案 1 :(得分:0)

这是我的看法。 WebClient本质上类似于此类的ToString方法。它获取所有键,然后一次检索一个值,并进行连接。因此,我重写了AllKeys以返回包含重复元素的数组。

例如,如果特定键具有多个值:

nvc["hello"] = { "a", "b", "c" }

然后,我的AllKeys将返回一个带有“ hello”的数组3次。 WebClient会天真地请求3次。字典会跟踪请求“ hello”的次数,然后每次返回一个不同的值(伪枚举器)

public class ParrotingNameValueCollection : NameValueCollection
{

    Dictionary<string, int> _indexTracker = new Dictionary<string, int>();

    public override string[] AllKeys
    {
        get
        {
            var l = new List<string>();
            foreach (var k in base.AllKeys)
            {
                foreach (var x in (ArrayList)base.BaseGet(k))
                    l.Add(k);

                _indexTracker[k] = 0;
            }
            
            return l.ToArray();
        }
    }


    public override string Get(string name)
    {

        var list = (ArrayList)base.BaseGet(name);

        var toReturn = (string)list[_indexTracker[name]];

        _indexTracker[name]++;

        return toReturn;
    }

    public override string ToString()
    {
        string delimiter = String.Empty;
        StringBuilder values = new StringBuilder();
        foreach (string name in this.AllKeys)
        {
            values.Append(delimiter);
            values.Append((name));
            values.Append("=");
            values.Append((this[name]));
            delimiter = "&";
        }

        return values.ToString();
    }
}