如何在C#中为URL创建查询字符串?

从代码调用Web资源时的常见任务是构建一个查询字符串以包含所有必要的参数。 虽然通过任何手段都不是火箭科学,但还是有一些你需要照顾的细节,附加一个&如果不是第一个参数,编码参数等等。

这样做的代码非常简单,但有点乏味:

StringBuilder SB = new StringBuilder();
if (NeedsToAddParameter A) 
{ 
  SB.Append("A="); SB.Append(HttpUtility.UrlEncode("TheValueOfA")); 
}

if (NeedsToAddParameter B) 
{
  if (SB.Length>0) SB.Append("&"); 
  SB.Append("B="); SB.Append(HttpUtility.UrlEncode("TheValueOfB")); }
}

这是一个常见的任务,人们会期望一个实用程序类的存在,使它更加优雅和可读。 扫描MSDN,我找不到一个 - 这给我带来了以下问题:

什么是你知道做上述最优雅干净的方式?


如果你仔细研究,QueryString属性是一个NameValueCollection。 当我做了类似的事情时,我通常对序列化和反序列化感兴趣,所以我的建议是建立一个NameValueCollection,然后传给:

using System.Web;
using System.Collections.Specialized;

private string ToQueryString(NameValueCollection nvc)
{
    var array = (from key in nvc.AllKeys
        from value in nvc.GetValues(key)
        select string.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value)))
        .ToArray();
    return "?" + string.Join("&", array);
}

可能我可以更好地格式化它:)

我想在LINQ中有一种超级优雅的方式可以做到这一点...


您可以通过调用System.Web.HttpUtility.ParseQueryString(string.Empty)创建一个新的HttpValueCollection可写实例,然后将其用作任何NameValueCollection 。 一旦你添加了你想要的值,你可以在集合上调用ToString来获得一个查询字符串,如下所示:

NameValueCollection queryString = System.Web.HttpUtility.ParseQueryString(string.Empty);

queryString["key1"] = "value1";
queryString["key2"] = "value2";

return queryString.ToString(); // Returns "key1=value1&key2=value2", all URL-encoded

HttpValueCollection是内部的,所以你不能直接构造一个实例。 但是,一旦你获得一个实例,你可以像使用其他的NameValueCollection一样使用它。 由于您使用的实际对象是HttpValueCollection ,因此调用ToString方法将调用HttpValueCollection上的重写方法,该方法将集合格式化为URL编码的查询字符串。

在搜索到和网络上的类似问题的答案之后,这是我能找到的最简单的解决方案。

.NET核心

如果您使用的是.NET Core,则可以使用Microsoft.AspNetCore.WebUtilities.QueryHelpers类,该类极大地简化了这一点。

https://docs.microsoft.com/en-us/aspnet/core/api/microsoft.aspnetcore.webutilities.queryhelpers


从Roy Tinker的评论中得到灵感,我最终在Uri类中使用了一个简单的扩展方法,它使我的代码简洁明了:

using System.Web;

public static class HttpExtensions
{
    public static Uri AddQuery(this Uri uri, string name, string value)
    {
        var httpValueCollection = HttpUtility.ParseQueryString(uri.Query);

        httpValueCollection.Remove(name);
        httpValueCollection.Add(name, value);

        var ub = new UriBuilder(uri);
        ub.Query = httpValueCollection.ToString();

        return ub.Uri;
    }
}

用法:

Uri url = new Uri("http://localhost/rest/something/browse").
          AddQuery("page", "0").
          AddQuery("pageSize", "200");

编辑 - 符合标准的变体

正如几个人指出的那样, httpValueCollection.ToString()以非标准兼容的方式编码Unicode字符。 这是通过调用HttpUtility.UrlEncode方法而不是废弃的HttpUtility.UrlEncodeUnicode方法处理此类字符的相同扩展方法的变体。

using System.Web;

public static Uri AddQuery(this Uri uri, string name, string value)
{
    var httpValueCollection = HttpUtility.ParseQueryString(uri.Query);

    httpValueCollection.Remove(name);
    httpValueCollection.Add(name, value);

    var ub = new UriBuilder(uri);

    // this code block is taken from httpValueCollection.ToString() method
    // and modified so it encodes strings with HttpUtility.UrlEncode
    if (httpValueCollection.Count == 0)
        ub.Query = String.Empty;
    else
    {
        var sb = new StringBuilder();

        for (int i = 0; i < httpValueCollection.Count; i++)
        {
            string text = httpValueCollection.GetKey(i);
            {
                text = HttpUtility.UrlEncode(text);

                string val = (text != null) ? (text + "=") : string.Empty;
                string[] vals = httpValueCollection.GetValues(i);

                if (sb.Length > 0)
                    sb.Append('&');

                if (vals == null || vals.Length == 0)
                    sb.Append(val);
                else
                {
                    if (vals.Length == 1)
                    {
                        sb.Append(val);
                        sb.Append(HttpUtility.UrlEncode(vals[0]));
                    }
                    else
                    {
                        for (int j = 0; j < vals.Length; j++)
                        {
                            if (j > 0)
                                sb.Append('&');

                            sb.Append(val);
                            sb.Append(HttpUtility.UrlEncode(vals[j]));
                        }
                    }
                }
            }
        }

        ub.Query = sb.ToString();
    }

    return ub.Uri;
}
链接地址: http://www.djcxy.com/p/26513.html

上一篇: How to build a query string for a URL in C#?

下一篇: Convert String to valid URI object