当从代码中调用web资源时,一个常见的任务是构建一个包含所有必要参数的查询字符串。虽然这绝不是火箭科学,但有一些漂亮的细节需要注意,例如,如果不是第一个参数,则添加&,对参数进行编码等。
实现它的代码非常简单,但有点乏味:
StringBuilder SB = new StringBuilder();
if (NeedsToAddParameter A)
{
SB.Append("A="); SB.Append(HttpUtility.UrlEncode("TheValueOfA"));
}
if (NeedsToAddParameter B)
{
if (SB.Length>0) SB.Append("&");
SB.Append("B="); SB.Append(HttpUtility.UrlEncode("TheValueOfB")); }
}
这是一个非常常见的任务,人们希望存在一个实用工具类,使其更加优雅和可读。扫描MSDN,我没有找到一个,这让我想到了以下问题:
你所知道的最优雅干净的方法是什么?
奇怪的是没有人提到来自asp.net . core的QueryBuilder。
当你有一个重复键的查询,比如?filter=a&filter=b,它会很有用
var qb = new QueryBuilder();
qb.Add("filter", new string[] {"A", "B"});
然后你只需要将qb添加到URI中,它就会自动转换为字符串。
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.extensions.querybuilder?view=aspnetcore-5.0
public static string ToQueryString(this Dictionary<string, string> source)
{
return String.Join("&", source.Select(kvp => String.Format("{0}={1}", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value))).ToArray());
}
public static string ToQueryString(this NameValueCollection source)
{
return String.Join("&", source.Cast<string>().Select(key => String.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(source[key]))).ToArray());
}
Flurl[披露:我是作者]支持通过匿名对象(以及其他方式)构建查询字符串:
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!"
});
可选的Flurl。Http companion lib允许您在相同的流畅调用链上执行Http调用,将其扩展为一个成熟的REST客户端:
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>();
完整的软件包在NuGet上可用:
PM>安装包Flurl。Http
或者只是独立的URL构建器:
PM>安装包Flurl
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();
}
}
}
使用示例:
QueryStringBuilder parameters = new QueryStringBuilder()
.Add("view", ViewBag.PageView)
.Add("page", ViewBag.PageNumber)
.Add("size", ViewBag.PageSize);
string queryString = parameters.ToString();
我需要为我正在开发的可移植类库(PCL)解决同样的问题。在这种情况下,我没有访问系统的权限。所以我不能用ParseQueryString。
相反,我使用System.Net.Http.FormUrlEncodedContent像这样:
var url = new UriBuilder("http://example.com");
url.Query = new FormUrlEncodedContent(new Dictionary<string,string>()
{
{"param1", "val1"},
{"param2", "val2"},
{"param3", "val3"},
}).ReadAsStringAsync().Result;