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

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


当前回答

接受答案的好部分,修改为使用UriBuilder.Uri.ParseQueryString()而不是HttpUtility.ParseQueryString():

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

其他回答

您可能想看看Flurl[披露:我是作者],这是一个流畅的URL构建器,带有可选的配套库,可以将其扩展为一个成熟的REST客户机。

var result = await "https://api.com"
    // basic URL building:
    .AppendPathSegment("endpoint")
    .SetQueryParams(new {
        api_key = ConfigurationManager.AppSettings["SomeApiKey"],
        max_results = 20,
        q = "Don't worry, I'll get encoded!"
    })
    .SetQueryParams(myDictionary)
    .SetQueryParam("q", "overwrite q!")

    // extensions provided by Flurl.Http:
    .WithOAuthBearerToken("token")
    .GetJsonAsync<TResult>();

查看文档了解更多细节。完整的软件包在NuGet上可用:

PM>安装包Flurl。Http

或者只是独立的URL构建器:

PM>安装包Flurl

如果我想使用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提供了一个有趣而聪明的解决方案,这里有一些可能是另一个选择:

public class ParameterCollection
{
    private Dictionary<string, string> _parms = new Dictionary<string, string>();

    public void Add(string key, string val)
    {
        if (_parms.ContainsKey(key))
        {
            throw new InvalidOperationException(string.Format("The key {0} already exists.", key));
        }
        _parms.Add(key, val);
    }

    public override string ToString()
    {
        var server = HttpContext.Current.Server;
        var sb = new StringBuilder();
        foreach (var kvp in _parms)
        {
            if (sb.Length > 0) { sb.Append("&"); }
            sb.AppendFormat("{0}={1}",
                server.UrlEncode(kvp.Key),
                server.UrlEncode(kvp.Value));
        }
        return sb.ToString();
    }
}

所以当你使用它时,你可以这样做:

var parms = new ParameterCollection();
parms.Add("key", "value");

var url = ...
url += "?" + parms;
HttpClient client = new HttpClient();
var uri = Environment.GetEnvironmentVariable("URL of Api");
                
var requesturi = QueryHelpers.AddQueryString(uri, "parameter_name",parameter_value);
client.BaseAddress = new Uri(requesturi);

然后你也可以添加请求头例如:

client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-key", secretValue);

响应语法eg:

HttpResponseMessage response = client.GetAsync(requesturi).Result;

希望它对你有用。

对于那些不想包括系统。Web在项目中还没有使用它,你可以使用System.Net.Http的FormUrlEncodedContent,并做如下的事情:

keyvaluepair版本

string query;
using(var content = new FormUrlEncodedContent(new KeyValuePair<string, string>[]{
    new KeyValuePair<string, string>("ham", "Glazed?"),
    new KeyValuePair<string, string>("x-men", "Wolverine + Logan"),
    new KeyValuePair<string, string>("Time", DateTime.UtcNow.ToString()),
})) {
    query = content.ReadAsStringAsync().Result;
}

字典的版本

string query;
using(var content = new FormUrlEncodedContent(new Dictionary<string, string>()
{
    { "ham", "Glaced?"},
    { "x-men", "Wolverine + Logan"},
    { "Time", DateTime.UtcNow.ToString() },
})) {
    query = content.ReadAsStringAsync().Result;
}