C# 为System.Net.HttpClient get生成查询字符串
如果我希望使用System.Net.HttpClient提交http get请求,则似乎没有用于添加参数的api,是否正确 是否有任何简单的api可用于构建查询字符串,而不涉及构建名称-值集合和url编码,然后最终连接它们? 我希望使用类似RestSharp的api(即AddParameter(…) 如果我希望使用System.Net.HttpClient提交http get请求 似乎没有api来添加参数,对吗 对 是否有任何简单的api可用于构建 不涉及构建名称-值集合和url编码 然后将它们连接起来 当然可以: 您可能还会发现C# 为System.Net.HttpClient get生成查询字符串,c#,.net,http,C#,.net,Http,如果我希望使用System.Net.HttpClient提交http get请求,则似乎没有用于添加参数的api,是否正确 是否有任何简单的api可用于构建查询字符串,而不涉及构建名称-值集合和url编码,然后最终连接它们? 我希望使用类似RestSharp的api(即AddParameter(…) 如果我希望使用System.Net.HttpClient提交http get请求 似乎没有api来添加参数,对吗 对 是否有任何简单的api可用于构建 不涉及构建名称-值集合和url编码 然后将它们
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();
您可以更安全地向您的
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();
}
}
或者简单地使用我的Uri扩展 代码 结果
您可能想查看[披露:我是作者],这是一个流畅的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>();
var结果=等待”https://api.com"
//基本URL构建:
.AppendPathSegment(“端点”)
.SetQueryParams(新{
api_key=ConfigurationManager.AppSettings[“SomeApiKey”],
最大结果=20,
q=“别担心,我会被编码的!”
})
.SetQueryParams(myDictionary)
.SetQueryParam(“q”,“覆盖q!”)
//Flurl.Http提供的扩展:
.使用OAuthBealerToken(“代币”)
.GetJsonAsync();
查看更多详细信息。NuGet上提供了完整的软件包:
PM>安装软件包Flurl.Http
或者仅使用独立的URL生成器:
PM>安装软件包Flurl
我正在开发的软件包能够执行此操作。所有编码都是按照RFC为您处理的。在撰写本文时,有一个beta版可用,它不被认为是稳定的1.0版的唯一原因是文档没有完全满足我的期望(请参阅问题,,)
您可以单独构建查询字符串:
UriTemplate template = new UriTemplate("{?params*}");
var parameters = new Dictionary<string, string>
{
{ "param1", "value1" },
{ "param2", "value2" },
};
Uri relativeUri = template.BindByName(parameters);
UriTemplate template=新的UriTemplate(“{?params*}”);
var参数=新字典
{
{“param1”,“value1”},
{“param2”,“value2”},
};
Uri relativeUri=template.BindByName(参数);
或者您可以构建一个完整的URI:
UriTemplate template = new UriTemplate("path/to/item{?params*}");
var parameters = new Dictionary<string, string>
{
{ "param1", "value1" },
{ "param2", "value2" },
};
Uri baseAddress = new Uri("http://www.example.com");
Uri relativeUri = template.BindByName(baseAddress, parameters);
UriTemplate-template=newuritemplate(“path/to/item{?params*}”);
var参数=新字典
{
{“param1”,“value1”},
{“param2”,“value2”},
};
Uri baseAddress=新Uri(“http://www.example.com");
Uri relativeUri=template.BindByName(基地址、参数);
对于那些不想将System.Web
包含在尚未使用它的项目中的人,您可以使用fromSystem.Net.Http
并执行以下操作:
keyvaluepair版本
字符串查询;
使用(var content=new FormUrlEncodedContent(new KeyValuePair[]{
新的KeyValuePair(“火腿”、“上釉?”),
新的KeyValuePair(“x战警”、“狼獾+洛根”),
新的KeyValuePair(“Time”,DateTime.UtcNow.ToString()),
})) {
query=content.ReadAsStringAsync().Result;
}
词典版本
字符串查询;
使用(var content=newformurlencodedcontent(newdictionary)()
{
{“火腿”,“糖衣?”},
{“x战警”,“狼獾+洛根”},
{“Time”,DateTime.UtcNow.ToString()},
})) {
query=content.ReadAsStringAsync().Result;
}
由于我必须重复使用这几次,我提出了这个类,它可以帮助抽象查询字符串的组成方式
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;
var builder=new-UriBuilderExt(“http://example.com/");
builder.AddParameter(“foo”、“bar&-baz”);
builder.AddParameter(“条”、“秒”);
var-uri=builder.uri;
这将返回uri:
多亏了“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();
}
}
公共静态部分类Ext
{
公共静态Uri GetUriWithparameters(此Uri,字典queryParams=null,int-port=-1)
{
var builder=新的UriBuilder(uri);
builder.Port=Port;
if(null!=queryParams&&0
我找不到比创建扩展方法将字典转换为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;
}
}
公共静态类字典text
{
公共静态字符串ToQueryString(此字典)
{
返回查询字符串(字典“?”);
}
公共静态字符串ToQueryString(此字典、字符串分隔符)
{
字符串结果=string.Empty;
foreach(字典中的变量项)
{
if(string.IsNullOrEmpty(result))
结果+=startupDelimiter;/“?”;
其他的
结果+=“&”;
结果+=str
UriTemplate template = new UriTemplate("{?params*}");
var parameters = new Dictionary<string, string>
{
{ "param1", "value1" },
{ "param2", "value2" },
};
Uri relativeUri = template.BindByName(parameters);
UriTemplate template = new UriTemplate("path/to/item{?params*}");
var parameters = new Dictionary<string, string>
{
{ "param1", "value1" },
{ "param2", "value2" },
};
Uri baseAddress = new Uri("http://www.example.com");
Uri relativeUri = template.BindByName(baseAddress, parameters);
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;
}
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;
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();
}
}
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¶m2=value2"
param.ToQueryString("&"); //Will add (&)
//"¶m1=value1¶m2=value2"
param.ToQueryString(""); //Won't add anything
//"param1=value1¶m2=value2"
var builder = new UriBuilder
{
Scheme = Uri.UriSchemeHttps,
Port = -1,
Host = "127.0.0.1",
Path = "app"
};
NameValueCollection query = HttpUtility.ParseQueryString(builder.Query);
query["cyrillic"] = "кирилиця";
builder.Query = query.ToString();
Console.WriteLine(builder.Query); //query with cyrillic stuff UrlEncodedUnicode, and that's not what you want
var uri = builder.Uri; // creates new Uri using constructor which does encode and messes cyrillic parameter even more
Console.WriteLine(uri);
// this is still wrong:
var stringUri = builder.ToString(); // returns more 'correct' (still `UrlEncodedUnicode`, but at least once, not twice)
new HttpClient().GetStringAsync(stringUri); // this creates Uri object out of 'stringUri' so we still end up sending double encoded cyrillic text to server. Ouch!
?cyrillic=%u043a%u0438%u0440%u0438%u043b%u0438%u0446%u044f
https://127.0.0.1/app?cyrillic=%25u043a%25u0438%25u0440%25u0438%25u043b%25u0438%25u0446%25u044f
var uri = new Uri(builder.ToString(), dontEscape: true);
new HttpClient().GetStringAsync(uri);
// using Microsoft.AspNetCore.WebUtilities;
var query = new Dictionary<string, string>
{
["foo"] = "bar",
["foo2"] = "bar2",
// ...
};
var response = await client.GetAsync(QueryHelpers.AddQueryString("/api/", query));
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();
var parameters = new Dictionary<string, string>()
{
{ "ham", "Glaced?" },
{ "x-men", "Wolverine + Logan" },
{ "Time", DateTime.UtcNow.ToString() },
};
var query = new FormDataCollection(parameters).ReadAsNameValueCollection().ToString();