Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为System.Net.HttpClient get生成查询字符串_C#_.net_Http - Fatal编程技术网

C# 为System.Net.HttpClient get生成查询字符串

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编码 然后将它们

如果我希望使用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
包含在尚未使用它的项目中的人,您可以使用from
System.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&param2=value2"
param.ToQueryString("&"); //Will add (&)
//"&param1=value1&param2=value2"
param.ToQueryString(""); //Won't add anything
//"param1=value1&param2=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();