UriBuilder ub = new UriBuilder(requestUri.AbsoluteUri);
if (param != null && (method == "GET" || method == "DELETE" || method == "HEAD"))
{
- ub.Query = CreateQueryString(param);
+ ub.Query = MyCommon.BuildQueryString(param);
}
HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(ub.Uri);
//POST/PUTメソッドの場合は、ボディデータとしてクエリ構成して書き込み
using (StreamWriter writer = new StreamWriter(webReq.GetRequestStream()))
{
- writer.Write(CreateQueryString(param));
+ writer.Write(MyCommon.BuildQueryString(param));
}
}
//cookie設定
}
///<summary>
- ///クエリコレクションをkey=value形式の文字列に構成して戻す
- ///</summary>
- ///<param name="param">クエリ、またはポストデータとなるkey-valueコレクション</param>
- protected string CreateQueryString(IDictionary<string, string> param)
- {
- if (param == null || param.Count == 0) return string.Empty;
-
- StringBuilder query = new StringBuilder();
- foreach (string key in param.Keys)
- {
- query.AppendFormat("{0}={1}&", QueryEncode(key), QueryEncode(param[key]));
- }
- return query.ToString(0, query.Length - 1);
- }
-
- ///<summary>
///クエリ形式(key1=value1&key2=value2&...)の文字列をkey-valueコレクションに詰め直し
///</summary>
///<param name="queryString">クエリ文字列</param>
return sb.ToString();
}
- ///<summary>
- ///2バイト文字も考慮したクエリ用エンコード
- ///</summary>
- ///<param name="stringToEncode">エンコードする文字列</param>
- ///<returns>エンコード結果文字列</returns>
- protected string QueryEncode(string stringToEncode)
- {
- // .NET 4.5+: Reserved characters のうち、Uriクラスによってエスケープ強制解除されてしまうものも最初から Unreserved として扱う
- const string UnreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!'()*:";
- StringBuilder sb = new StringBuilder();
- byte[] bytes = Encoding.UTF8.GetBytes(stringToEncode);
-
- foreach (byte b in bytes)
- {
- if (UnreservedChars.IndexOf((char)b) != -1)
- sb.Append((char)b);
- else
- sb.AppendFormat("%{0:X2}", b);
- }
- return sb.ToString();
- }
-
#region "InstanceTimeout"
///<summary>
///通信タイムアウト時間(ms)
// パラメタをソート済みディクショナリに詰替(OAuthの仕様)
SortedDictionary< string, string > sorted = new SortedDictionary< string, string >( parameter );
// URLエンコード済みのクエリ形式文字列に変換
- string paramString = this.CreateQueryString( sorted );
+ string paramString = MyCommon.BuildQueryString( sorted );
// アクセス先URLの整形
string url = string.Format( "{0}://{1}{2}", uri.Scheme, uri.Host, uri.AbsolutePath );
// 署名のベース文字列生成(&区切り)。クエリ形式文字列は再エンコードする
//パラメタをソート済みディクショナリに詰替(OAuthの仕様)
SortedDictionary<string, string> sorted = new SortedDictionary<string, string>(parameter);
//URLエンコード済みのクエリ形式文字列に変換
- string paramString = CreateQueryString(sorted);
+ string paramString = MyCommon.BuildQueryString(sorted);
//アクセス先URLの整形
string url = string.Format("{0}://{1}{2}", uri.Scheme, uri.Host, uri.AbsolutePath);
//本来のアクセス先URLに再設定(api.twitter.com固定)
return client;
}
+
+ /// <summary>
+ /// 指定された IDictionary を元にクエリ文字列を生成します
+ /// </summary>
+ /// <param name="param">生成するクエリの key-value コレクション</param>
+ public static string BuildQueryString(IDictionary<string, string> param)
+ {
+ if (param == null || param.Count == 0)
+ return string.Empty;
+
+ var query = param
+ .Where(x => x.Value != null)
+ .Select(x => EscapeQueryString(x.Key) + '=' + EscapeQueryString(x.Value));
+
+ return string.Join("&", query);
+ }
+
+ // .NET 4.5+: Reserved characters のうち、Uriクラスによってエスケープ強制解除されてしまうものも最初から Unreserved として扱う
+ private static readonly HashSet<char> UnreservedChars =
+ new HashSet<char>("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!'()*:");
+
+ /// <summary>
+ /// 2バイト文字も考慮したクエリ用エンコード
+ /// </summary>
+ /// <param name="stringToEncode">エンコードする文字列</param>
+ /// <returns>エンコード結果文字列</returns>
+ public static string EscapeQueryString(string stringToEncode)
+ {
+ var sb = new StringBuilder(stringToEncode.Length * 2);
+
+ foreach (var b in Encoding.UTF8.GetBytes(stringToEncode))
+ {
+ if (UnreservedChars.Contains((char)b))
+ sb.Append((char)b);
+ else
+ sb.AppendFormat("%{0:X2}", b);
+ }
+
+ return sb.ToString();
+ }
}
}