如果我想使用System.Net.HttpClient提交一个http获取请求,似乎没有api来添加参数,这是正确的吗?

是否有任何简单的api可用来构建查询字符串,不涉及构建名称值集合和url编码,然后最后连接它们? 我希望使用类似RestSharp的api(即AddParameter(..))


当前回答

在一个ASP。在asp.net Core项目中,你可以使用QueryHelpers类,在Microsoft.AspNetCore.WebUtilities命名空间中。NET Core,或。NET标准2.0 NuGet包给其他消费者:

// using Microsoft.AspNetCore.WebUtilities;
var query = new Dictionary<string, string>
{
    ["foo"] = "bar",
    ["foo2"] = "bar2",
    // ...
};

var response = await client.GetAsync(QueryHelpers.AddQueryString("/api/", query));

其他回答

我找不到比创建一个扩展方法来将Dictionary转换为QueryStringFormat更好的解决方案。Waleed A.K.提出的解决方案也不错。

遵循我的解决方案:

创建扩展方法:

public static class DictionaryExt
{
    public static string ToQueryString<TKey, TValue>(this Dictionary<TKey, TValue> dictionary)
    {
        return ToQueryString<TKey, TValue>(dictionary, "?");
    }

    public static string ToQueryString<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, string startupDelimiter)
    {
        string result = string.Empty;
        foreach (var item in dictionary)
        {
            if (string.IsNullOrEmpty(result))
                result += startupDelimiter; // "?";
            else
                result += "&";

            result += string.Format("{0}={1}", item.Key, item.Value);
        }
        return result;
    }
}

和他们:

var param = new Dictionary<string, string>
          {
            { "param1", "value1" },
            { "param2", "value2" },
          };
param.ToQueryString(); //By default will add (?) question mark at begining
//"?param1=value1&param2=value2"
param.ToQueryString("&"); //Will add (&)
//"&param1=value1&param2=value2"
param.ToQueryString(""); //Won't add anything
//"param1=value1&param2=value2"

由于我必须重用这几次,所以我提出了这个类,它只是帮助抽象查询字符串是如何组成的。

public class UriBuilderExt
{
    private NameValueCollection collection;
    private UriBuilder builder;

    public UriBuilderExt(string uri)
    {
        builder = new UriBuilder(uri);
        collection = System.Web.HttpUtility.ParseQueryString(string.Empty);
    }

    public void AddParameter(string key, string value) {
        collection.Add(key, value);
    }

    public Uri Uri{
        get
        {
            builder.Query = collection.ToString();
            return builder.Uri;
        }
    }

}

使用将被简化成这样:

var builder = new UriBuilderExt("http://example.com/");
builder.AddParameter("foo", "bar<>&-baz");
builder.AddParameter("bar", "second");
var uri = builder.Uri;

将返回uri: http://example.com/?foo=bar%3c%3e%26-baz&bar=second

如果我想使用System.Net.HttpClient提交一个http get请求 似乎没有API来添加参数,这是正确的吗?

Yes.

是否有任何简单的api可用来构建查询字符串 不涉及构建名称值集合和url编码 然后最后把它们连接起来?

肯定的:

var query = HttpUtility.ParseQueryString(string.Empty);
query["foo"] = "bar<>&-baz";
query["bar"] = "bazinga";
string queryString = query.ToString();

会给你预期的结果:

foo=bar%3c%3e%26-baz&bar=bazinga

你可能还会发现UriBuilder类很有用:

var builder = new UriBuilder("http://example.com");
builder.Port = -1;
var query = HttpUtility.ParseQueryString(builder.Query);
query["foo"] = "bar<>&-baz";
query["bar"] = "bazinga";
builder.Query = query.ToString();
string url = builder.ToString();

会给你预期的结果:

http://example.com/?foo=bar%3c%3e%26-baz&bar=bazinga

你可以非常安全地将它提供给HttpClient。GetAsync方法。

感谢“Darin Dimitrov”,这是扩展方法。

 public static partial class Ext
{
    public static Uri GetUriWithparameters(this Uri uri,Dictionary<string,string> queryParams = null,int port = -1)
    {
        var builder = new UriBuilder(uri);
        builder.Port = port;
        if(null != queryParams && 0 < queryParams.Count)
        {
            var query = HttpUtility.ParseQueryString(builder.Query);
            foreach(var item in queryParams)
            {
                query[item.Key] = item.Value;
            }
            builder.Query = query.ToString();
        }
        return builder.Uri;
    }

    public static string GetUriWithparameters(string uri,Dictionary<string,string> queryParams = null,int port = -1)
    {
        var builder = new UriBuilder(uri);
        builder.Port = port;
        if(null != queryParams && 0 < queryParams.Count)
        {
            var query = HttpUtility.ParseQueryString(builder.Query);
            foreach(var item in queryParams)
            {
                query[item.Key] = item.Value;
            }
            builder.Query = query.ToString();
        }
        return builder.Uri.ToString();
    }
}

与罗斯托夫的帖子一样,如果你不想包含对系统的引用。在你的项目中,你可以使用System.Net.Http.Formatting中的FormDataCollection,然后做如下的事情:

使用System.Net.Http.Formatting.FormDataCollection

var parameters = new Dictionary<string, string>()
{
    { "ham", "Glaced?" },
    { "x-men", "Wolverine + Logan" },
    { "Time", DateTime.UtcNow.ToString() },
}; 
var query = new FormDataCollection(parameters).ReadAsNameValueCollection().ToString();