NameValueCollection URL查询?

我知道我可以做到这一点

var nv = HttpUtility.ParseQueryString(req.RawUrl); 

但有没有办法将其转换回url?

 var newUrl = HttpUtility.Something("/page", nv); 

只需在NameValueCollection上调用ToString() ,将以name1=value1&name2=value2查询string就绪格式返回名称值对。 请注意, NameValueCollectiontypes实际上并不支持这一点,它是误导性的build议,但行为在这里工作,由于实际返回的内部types,如下所述。

感谢@mjwills指出HttpUtility.ParseQueryString方法实际上返回一个内部的HttpValueCollection对象,而不是一个常规的NameValueCollection ( 尽pipe文档指定了NameValueCollection )。 当使用ToString()HttpValueCollection自动对查询string进行编码,因此不需要编写循环遍历集合的例程并使用UrlEncode方法。 所需的结果已经返回。

结果在手,你可以把它附加到URL并redirect:

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

目前使用HttpValueCollection的唯一方法是使用上面显示的ParseQueryString方法(当然除了reflection)。 看起来这不会改变,因为请求这个类的连接问题被公开已经被closures,状态是“不会修复”。

另外,您可以调用nameValues上的AddSetRemove方法来修改任何查询string项目,然后再附加它。 如果您对此感兴趣, 请参阅我对另一个问题的回答 。

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

其实,你也应该把密钥编码,而不仅仅是价值。

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

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

 public static string ToQueryString(this NameValueCollection nvc) { StringBuilder sb = new StringBuilder(); foreach (string key in nvc.Keys) { if (string.IsNullOrEmpty(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(); } 

 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()); 

产量

 ?order_id=0000&item_id=1111&item_id=2222&needs%20escaping=special%20chars%20%3F%20%3D%20%26 

简短的答案是在NameValueCollection上使用.ToString() ,并将其与原始URL结合起来。

不过,我想指出一些事情:

你不能使用Request.RawUrl HttpUtility.ParseQueryStringParseQueryString()方法正在寻找这样的值: ?var=value&var2=value2

如果你想获得QueryString参数的NameValueCollection ,只需使用Request.QueryString()

 var nv = Request.QueryString; 

重buildURL只需使用nv.ToString()。

 string url = String.Format("{0}?{1}", Request.Path, nv.ToString()); 

如果您尝试parsingurlstring而不是使用Request对象, Request使用UriHttpUtility.ParseQueryString方法。

 Uri uri = new Uri("<THE URL>"); var nv = HttpUtility.ParseQueryString(uri.Query); string url = String.Format("{0}?{1}", uri.AbsolutePath, nv.ToString()); 

因为一个NameValueCollection对于同一个键可以有多个值,所以如果你关心查询string的格式(因为它会以逗号分隔的值而不是“数组符号”的forms返回),你可以考虑下面的内容。

 var nvc = new NameValueCollection(); nvc.Add("key1", "val1"); nvc.Add("key2", "val2"); nvc.Add("empty", null); nvc.Add("key2", "val2b"); 

转入: 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) ); }) ); 

或者如果你不喜欢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); } } } } 

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

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

这会为你工作吗?

 public static string BuildUrl(string relativeUrl, params string[] queryString) { // build queryString from string parameters char[] trimChars = { ' ', '&', '?' }; StringBuilder builder = new StringBuilder(); string sepChar = "&"; string sep = String.Empty; foreach (string q in queryString) { builder.Append(sep).Append(q.Trim(trimChars)); sep = sepChar; } if (String.IsNullOrEmpty(builder.ToString())) { return relativeUrl; } else { return relativeUrl + "?" + builder.ToString(); } } 

使用:

 string url = BuildUrl("/mypage.apsx", "qs1=a", "qs2=b", "qs3=c"); 

这应该没有太多的代码工作:

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

这个想法是使用HttpUtility.ParseQueryString来生成一个types为HttpValueCollection 。 这个类是NameValueCollection一个子类,被标记为internal所以你的代码不能轻易地创build它的一个实例。

HttpValueCollection在于ToString方法为你编码。 通过利用NameValueCollection.Add(NameValueCollection)方法,您可以将现有的查询string参数添加到新创build的对象,而不必先将Request.QueryString集合转换为url编码的string,然后将其parsing回集合中。

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

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

您可以使用。

 var ur = new Uri("/page",UriKind.Relative); 

如果这个nv是stringtypes,你可以追加到uri的第一个参数。 喜欢

 var ur2 = new Uri("/page?"+nv.ToString(),UriKind.Relative); 

我总是使用UriBuilder将具有查询string的url转换回有效且正确编码的url。

 var url = "http://my-link.com?foo=bar"; var uriBuilder = new UriBuilder(url); var query = HttpUtility.ParseQueryString(uriBuilder.Query); query.Add("yep", "foo&bar"); uriBuilder.Query = query.ToString(); var result = uriBuilder.ToString(); // http://my-link.com:80/?foo=bar&yep=foo%26bar