NameValueCollection到URL查询?

69 asp.net url namevaluecollection url-encoding

我知道我能做到这一点

var nv = HttpUtility.ParseQueryString(req.RawUrl);
Run Code Online (Sandbox Code Playgroud)

但有没有办法将其转换回网址?

var newUrl = HttpUtility.Something("/page", nv);
Run Code Online (Sandbox Code Playgroud)

Ahm*_*eed 104

只需调用ToString()NameValueCollection就会以name1=value1&name2=value2querystring ready格式返回名称值对.请注意,NameValueCollection类型实际上并不支持这种情况,并且建议这样做会产生误导,但由于实际返回的内部类型,此行为在此处起作用,如下所述.

感谢@mjwills指出该HttpUtility.ParseQueryString方法实际上返回的是内部HttpValueCollection对象而不是常规对象NameValueCollection(尽管文档指定NameValueCollection).使用时会HttpValueCollection自动对查询字符串进行编码ToString(),因此无需编写循环遍历集合并使用该UrlEncode方法的例程.已返回所需的结果.

有了结果,您可以将其附加到URL并重定向:

var nameValues = HttpUtility.ParseQueryString(Request.QueryString.ToString());
string url = Request.Url.AbsolutePath + "?" + nameValues.ToString();
Response.Redirect(url);
Run Code Online (Sandbox Code Playgroud)

目前使用a的唯一方法HttpValueCollection是使用ParseQueryString上面显示的方法(当然不是反射).看起来这不会改变,因为请求此类公开Connect问题已关闭,状态为"将无法修复".

顺便说一句,你可以调用Add,Set以及Remove对方法nameValues,以追加之前修改任何查询字符串的项目.如果您对此感兴趣,请参阅我对其他问题的回复.

  • `NameValueCollection.ToString()`返回`System.Collections.Specialized.NameValueCollection`字符串(字面意思),而不是"查询字符串就绪格式的名称值对". (36认同)
  • 实际上你可以使用qs.ToString().这是因为qs不是NameValueCollection(尽管HttpUtility.ParseQueryString的方法签名).它实际上是一个名为System.Web.HttpValueCollection的私有类型(您可以使用qs.GetType()来检查它).NameValueCollection.ToString()不是url编码,但是HttpValueCollection.ToString()可以.所以你完全没必要使用StringBuilder. (9认同)
  • 我之前的评论可能不正确.HttpValueCollection不会调用HttpUtility.UrlEncode - 而是似乎调用HttpUtility.UrlEncodeUnicode(http://tinyurl.com/HttpValue).这是一个问题,因为两者在处理某些字符(例如é)方面存在差异.UrlEncodeUnicode的新文档似乎暗示不应该使用它 - http://msdn.microsoft.com/en-us/library/system.web.httputility.urlencodeunicode(v=vs.110).aspx. (8认同)
  • @IgorBrejc谢谢,我已更新我的帖子,说它有误导性地说'NameValueCollection`返回预期的格式.MSDN文档也有误导性,因为它说`ParseQueryString`返回一个`NameValueCollection`,虽然它实际上是`HttpValueCollection`并且调用`ToString()`就应该返回预期的格式,因为其余的答案都提到了. (4认同)
  • 我不确定nameValues.ToString()会正确转义. (2认同)
  • 我还发现NameValueCollection.ToString()没有格式化为查询字符串. (2认同)
  • 继我之前的评论之后,这里的解决方案将可靠地工作,但**只有**如果你将`aspnet:DontUsePercentUUrlEncoding`设置为true.请参阅http://www.andornot.com/blog/post/Beware-NameValueCollectionToString-and-DontUsePercentUUrlEncoding.aspx. (2认同)

Den*_*nis 63

string q = String.Join("&",
             nvc.AllKeys.Select(a => a + "=" + HttpUtility.UrlEncode(nvc[a])));
Run Code Online (Sandbox Code Playgroud)

  • 也是唯一一个回答关于`NameValueCollections`的文字问题,而不是提供的涉及`HttpValueCollection`的场景 (6认同)
  • 如果同一个键有多个值,我认为这不会正常工作. (4认同)
  • @MartinBrown是对的,它没有.这适用于多值namevaluecollections:uriBuilder.Query + = String.Join("&",parameters.AllKeys.SelectMany(key =>(parameters.GetValues(key)?? Enumerable.Empty <string>()).选择( val => String.Concat(key,"=",WebUtility.UrlEncode(val))))); (2认同)
  • 您也应该对密钥进行编码:`string q = String.Join(“&”,nvc.AllKeys.Select(a =&gt; HttpUtility.UrlEncode(a)+“ =” + HttpUtility.UrlEncode(nvc [a]))) ;` (2认同)

Mat*_*ger 14

创建一个使用几个循环的扩展方法.我更喜欢这个解决方案,因为它是可读的(没有linq),不需要System.Web.HttpUtility,它处理重复的键.

public static string ToQueryString(this NameValueCollection nvc)
{
    if (nvc == null) return string.Empty;

    StringBuilder sb = new StringBuilder();

    foreach (string key in nvc.Keys)
    {
        if (string.IsNullOrWhiteSpace(key)) continue;

        string[] values = nvc.GetValues(key);
        if (values == null) continue;

        foreach (string value in values)
        {
            sb.Append(sb.Length == 0 ? "?" : "&");
            sb.AppendFormat("{0}={1}", Uri.EscapeDataString(key), Uri.EscapeDataString(value));
        }
    }

    return sb.ToString();
}
Run Code Online (Sandbox Code Playgroud)

var queryParams = new NameValueCollection()
{
    { "order_id", "0000" },
    { "item_id", "1111" },
    { "item_id", "2222" },
    { null, "skip entry with null key" },
    { "needs escaping", "special chars ? = &" },
    { "skip entry with null value", null }
};

Console.WriteLine(queryParams.ToQueryString());
Run Code Online (Sandbox Code Playgroud)

产量

?order_id=0000&item_id=1111&item_id=2222&needs%20escaping=special%20chars%20%3F%20%3D%20%26
Run Code Online (Sandbox Code Playgroud)


dan*_*ana 12

这应该没有太多代码:

NameValueCollection nameValues = HttpUtility.ParseQueryString(String.Empty);
nameValues.Add(Request.QueryString);
// modify nameValues if desired
var newUrl = "/page?" + nameValues;
Run Code Online (Sandbox Code Playgroud)

这个想法是用来HttpUtility.ParseQueryString生成一个空的类型集合HttpValueCollection.此类是其子类NameValueCollection,标记为internal您的代码无法轻松创建它的实例.

好处HttpValueCollection是该ToString方法为您处理编码.通过利用该NameValueCollection.Add(NameValueCollection)方法,您可以将现有的查询字符串参数添加到新创建的对象中,而无需先将Request.QueryString集合转换为url编码的字符串,然后将其解析回集合.

此技术也可以作为扩展方法公开:

public static string ToQueryString(this NameValueCollection nameValueCollection)
{
    NameValueCollection httpValueCollection = HttpUtility.ParseQueryString(String.Empty);
    httpValueCollection.Add(nameValueCollection);
    return httpValueCollection.ToString();
}
Run Code Online (Sandbox Code Playgroud)


drz*_*aus 5

因为NameValueCollection同一个键可以有多个值,所以如果您关心查询字符串的格式(因为它将作为逗号分隔值而不是“数组表示法”返回),您可以考虑以下内容。

例子

var nvc = new NameValueCollection();
nvc.Add("key1", "val1");
nvc.Add("key2", "val2");
nvc.Add("empty", null);
nvc.Add("key2", "val2b");
Run Code Online (Sandbox Code Playgroud)

变成:key1=val1&key2[]=val2&empty&key2[]=val2b而不是key1=val1&key2=val2,val2b&empty

代码

string qs = string.Join("&", 
    // "loop" the keys
    nvc.AllKeys.SelectMany(k => {
        // "loop" the values
        var values = nvc.GetValues(k);
        if(values == null) return new[]{ k };
        return nvc.GetValues(k).Select( (v,i) => 
            // 'gracefully' handle formatting
            // when there's 1 or more values
            string.Format(
                values.Length > 1
                    // pick your array format: k[i]=v or k[]=v, etc
                    ? "{0}[]={1}"
                    : "{0}={1}"
                , k, HttpUtility.UrlEncode(v), i)
        );
    })
);
Run Code Online (Sandbox Code Playgroud)

或者如果你不太喜欢 Linq...

string qs = nvc.ToQueryString(); // using...

public static class UrlExtensions {
    public static string ToQueryString(this NameValueCollection nvc) {
        return string.Join("&", nvc.GetUrlList());
    }

    public static IEnumerable<string> GetUrlList(this NameValueCollection nvc) {
        foreach(var k in nvc.AllKeys) {
            var values = nvc.GetValues(k);
            if(values == null)  { yield return k; continue; }
            for(int i = 0; i < values.Length; i++) {
                yield return
                // 'gracefully' handle formatting
                // when there's 1 or more values
                string.Format(
                    values.Length > 1
                        // pick your array format: k[i]=v or k[]=v, etc
                        ? "{0}[]={1}"
                        : "{0}={1}"
                    , k, HttpUtility.UrlEncode(values[i]), i);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如评论中已经指出的那样,除了这个答案之外,大多数其他答案都解决了场景(Request.QueryString是一个HttpValueCollection,“不是”a NameValueCollection)而不是字面问题。

更新:解决了评论中的空值问题。


小智 5

实际上,你也应该对键进行编码,而不仅仅是值.

string q = String.Join("&",
nvc.AllKeys.Select(a => $"{HttpUtility.UrlEncode(a)}={HttpUtility.UrlEncode(nvc[a])}"));
Run Code Online (Sandbox Code Playgroud)


Gab*_*ães -2

您可以使用。

var ur = new Uri("/page",UriKind.Relative);
Run Code Online (Sandbox Code Playgroud)

如果此 nv 是字符串类型,您可以附加到 uri 第一个参数。喜欢

var ur2 = new Uri("/page?"+nv.ToString(),UriKind.Relative);
Run Code Online (Sandbox Code Playgroud)