How to build a query string for a URL in C#?

前端 未结 30 2534
借酒劲吻你
借酒劲吻你 2020-11-22 01:55

A common task when calling web resources from a code is building a query string to including all the necessary parameters. While by all means no rocket science, there are so

相关标签:
30条回答
  • 2020-11-22 02:20

    Flurl [disclosure: I'm the author] supports building query strings via anonymous objects (among other ways):

    var url = "http://www.some-api.com".SetQueryParams(new
    {
        api_key = ConfigurationManager.AppSettings["SomeApiKey"],
        max_results = 20,
        q = "Don't worry, I'll get encoded!"
    });
    

    The optional Flurl.Http companion lib allows you to do HTTP calls right off the same fluent call chain, extending it into a full-blown REST client:

    T result = await "https://api.mysite.com"
        .AppendPathSegment("person")
        .SetQueryParams(new { ap_key = "my-key" })
        .WithOAuthBearerToken("MyToken")
        .PostJsonAsync(new { first_name = firstName, last_name = lastName })
        .ReceiveJson<T>();
    

    The full package is available on NuGet:

    PM> Install-Package Flurl.Http

    or just the stand-alone URL builder:

    PM> Install-Package Flurl

    0 讨论(0)
  • 2020-11-22 02:20

    Just wanted to throw in my 2 cents:

    public static class HttpClientExt
    {
        public static Uri AddQueryParams(this Uri uri, string query)
        {
            var ub = new UriBuilder(uri);
            ub.Query = string.IsNullOrEmpty(uri.Query) ? query : string.Join("&", uri.Query.Substring(1), query);
            return ub.Uri;
        }
    
        public static Uri AddQueryParams(this Uri uri, IEnumerable<string> query)
        {
            return uri.AddQueryParams(string.Join("&", query));
        } 
    
        public static Uri AddQueryParams(this Uri uri, string key, string value)
        {
            return uri.AddQueryParams(string.Join("=", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value)));
        }
    
        public static Uri AddQueryParams(this Uri uri, params KeyValuePair<string,string>[] kvps)
        {
            return uri.AddQueryParams(kvps.Select(kvp => string.Join("=", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value))));
        }
    
        public static Uri AddQueryParams(this Uri uri, IDictionary<string, string> kvps)
        {
            return uri.AddQueryParams(kvps.Select(kvp => string.Join("=", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value))));
        }
    
        public static Uri AddQueryParams(this Uri uri, NameValueCollection nvc)
        {
            return uri.AddQueryParams(nvc.AllKeys.SelectMany(nvc.GetValues, (key, value) => string.Join("=", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value))));
        }
    }
    

    The docs say that uri.Query will start with a ? if it's non-empty and you should trim it off if you're going to modify it.

    Note that HttpUtility.UrlEncode is found in System.Web.

    Usage:

    var uri = new Uri("https://api.del.icio.us/v1/posts/suggest").AddQueryParam("url","http://stackoverflow.com")
    
    0 讨论(0)
  • 2020-11-22 02:20

    I went with the solution proposed by DSO (answered on Aug 2 '11 at 7:29), his solution does not require using HttpUtility. However, as per an article posted in Dotnetpearls, using a Dictionary is faster (in performance) than using NameValueCollection. Here is DSO's solution modified to use Dictionary in place of NameValueCollection.

        public static Dictionary<string, string> QueryParametersDictionary()
        {
            var dictionary = new Dictionary<string, string>();
            dictionary.Add("name", "John Doe");
            dictionary.Add("address.city", "Seattle");
            dictionary.Add("address.state_code", "WA");
            dictionary.Add("api_key", "5352345263456345635");
    
            return dictionary;
        }
    
        public static string ToQueryString(Dictionary<string, string> nvc)
        {
            StringBuilder sb = new StringBuilder();
    
            bool first = true;
    
            foreach (KeyValuePair<string, string> pair in nvc)
            {
                    if (!first)
                    {
                        sb.Append("&");
                    }
    
                    sb.AppendFormat("{0}={1}", Uri.EscapeDataString(pair.Key), Uri.EscapeDataString(pair.Value));
    
                    first = false;
            }
    
            return sb.ToString();
        }
    
    0 讨论(0)
  • 2020-11-22 02:21

    Chain-able wrapper class for HttpValueCollection:

    namespace System.Web.Mvc {
        public class QueryStringBuilder {
            private NameValueCollection collection;
            public QueryStringBuilder() {
                collection = System.Web.HttpUtility.ParseQueryString(string.Empty);
            }
            public QueryStringBuilder Add(string key, string value) {
                collection.Add(key, value);
                return this;
            }
            public QueryStringBuilder Remove(string key) {
                collection.Remove(key);
                return this;
            }
            public string this[string key] {
                get { return collection[key]; }
                set { collection[key] = value; }
            }
            public string ToString() {
                return collection.ToString();
            }
        }
    }
    

    Example usage:

    QueryStringBuilder parameters = new QueryStringBuilder()
        .Add("view", ViewBag.PageView)
        .Add("page", ViewBag.PageNumber)
        .Add("size", ViewBag.PageSize);
    string queryString = parameters.ToString();
    
    0 讨论(0)
  • 2020-11-22 02:22

    My offering:

    public static Uri AddQuery(this Uri uri, string name, string value)
    {
        // this actually returns HttpValueCollection : NameValueCollection
        // which uses unicode compliant encoding on ToString()
        var query = HttpUtility.ParseQueryString(uri.Query);
    
        query.Add(name, value);
    
        var uriBuilder = new UriBuilder(uri)
        {
            Query = query.ToString()
        };
    
        return uriBuilder.Uri;
    }
    

    Usage:

    var uri = new Uri("http://stackoverflow.com").AddQuery("such", "method")
                                                 .AddQuery("wow", "soFluent");
    
    // http://stackoverflow.com?such=method&wow=soFluent
    
    0 讨论(0)
  • 2020-11-22 02:22

    Untested, but I think something along these lines would work quite nicely

    public class QueryString
    {
        private Dictionary<string,string> _Params = new Dictionary<string,string>();
    
        public overide ToString()
        {
            List<string> returnParams = new List<string>();
    
            foreach (KeyValuePair param in _Params)
            {
                returnParams.Add(String.Format("{0}={1}", param.Key, param.Value));
            }
    
            // return String.Format("?{0}", String.Join("&", returnParams.ToArray())); 
    
            // credit annakata
            return "?" + String.Join("&", returnParams.ToArray());
        }
    
        public void Add(string key, string value)
        {
            _Params.Add(key, HttpUtility.UrlEncode(value));
        }
    }
    
    QueryString query = new QueryString();
    
    query.Add("param1", "value1");
    query.Add("param2", "value2");
    
    return query.ToString();
    
    0 讨论(0)
提交回复
热议问题