回答:
EscapeDataString
常に使用(理由の詳細については、以下のLivvenの回答を参照)
編集:2つのエンコーディングの違いへのデッドリンクを削除
URLEncode
あまりにも比較しています)。
既存の回答で満足できる結果が得られなかったため、この問題を解決するためにもう少し掘り下げることにしました。驚いたことに、答えは非常に簡単です。
(ほとんど*)を使用する正当な理由はありませんUri.EscapeUriString
。文字列をパーセントエンコードする必要がある場合は、常にを使用してくださいUri.EscapeDataString
。
*有効な使用例については、最後の段落を参照してください。
どうしてこれなの?ドキュメントによると:
EscapeUriStringメソッドを使用して、エスケープされていないURI文字列をUriコンストラクターのパラメーターとして準備します。
これは実際には意味がありません。RFC 2396によると:
完成したURIをエスケープまたはエスケープ解除するとセマンティクスが変わる可能性があるため、URIは常に「エスケープ」形式になります。
引用されたRFCはRFC 3986によって廃止されましたが、要点はまだ残っています。いくつかの具体例を見て確認しましょう。
次のような単純なURIがあります。
http://example.org/
Uri.EscapeUriString
変更されません。
エスケープを考慮せずに、クエリ文字列を手動で編集することにしました。
http://example.org/?key=two words
Uri.EscapeUriString
(正しく)スペースをエスケープします:
http://example.org/?key=two%20words
さらに、クエリ文字列を手動で編集することにしました。
http://example.org/?parameter=father&son
ただし、この文字列はUri.EscapeUriString
アンパサンドが別のキーと値のペアの開始を表すと想定しているため、では変更されません。これは、意図したものである場合とそうでない場合があります。
実際にはkey
パラメーターをにしたいと判断したfather&son
ので、アンパサンドをエスケープして、以前のURLを手動で修正します。
http://example.org/?parameter=father%26son
ただし、Uri.EscapeUriString
パーセント文字もエスケープし、二重エンコードにつながります。
http://example.org/?parameter=father%2526son
ご覧のとおりUri.EscapeUriString
、意図した目的で使用する&
と、複数のキーと値のペア間の区切り文字としてではなく、クエリ文字列のキーまたは値の一部として使用できなくなります。
これは、完全なURIをエスケープするのに適したものにするために、予約文字を無視して、予約も予約もされていない文字のみをエスケープするためです。BTWは、ドキュメントに反しています。このようにすると、のような結果http%3A%2F%2Fexample.org%2F
になることはありませんが、上記の問題が発生します。
結局のところ、URIが有効であれば、それをエスケープしてパラメーターとしてUriコンストラクターに渡す必要はありません。また、URIが有効でない場合、呼び出しUri.EscapeUriString
も魔法の解決策ではありません。実際、ほとんどの場合ではなくても多くの場合に機能しますが、信頼できるとは限りません。
キーと値のペアとパーセントエンコーディングを収集し、それらを必要な区切り記号で連結することにより、常にURLとクエリ文字列を作成する必要があります。上記のように予約文字をエスケープしないため、Uri.EscapeDataString
この目的には使用できますが、には使用できUri.EscapeUriString
ません。
ユーザー提供のURIを処理する場合など、それができない場合にのみUri.EscapeUriString
、最後の手段として使用することは理にかなっています。ただし、前述の警告が適用されます。ユーザーが指定したURIが不明確な場合、結果が望ましくない場合があります。
encodeURI
/ Uri.EscapeUriString
が多いほど必要とされていないencodeURIComponent
/ Uri.EscapeDataString
(あなたは、URIのコンテキストで使用されなければならないブラインドURLをdeaingされたとき以来の)、それはその場所を持っていないという意味ではありません。
プラス(+)文字は、これらの方法の違いを明らかにします。単純なURIでは、プラス記号は「スペース」を意味します。「ハッピーキャット」についてGoogleにクエリすることを検討してください:
これは有効なURI(試してみてください)であり、EscapeUriString
変更することはありません。
次に、Googleに「ハッピーc ++」をクエリすることを検討してください。
これは有効なURIです(試してみてください)。ただし、2つのプラス記号はスペースとして解釈されるため、「ハッピーc」を検索します。それを修正するために、我々は「幸せなC ++」に渡すことができEscapeDataString
出来上がり*を:
*)エンコードされたデータ文字列は、実際には「happy%20c%2B%2B」です。%20はスペース文字の16進数で、%2Bはプラス文字の16進数です。
本来の方法で使用しUriBuilder
ている場合は、EscapeDataString
URI全体の一部のコンポーネントを適切にエスケープするだけで済みます。この質問に対する@Livvenの回答は、実際に使用する理由がないことをさらに証明していますEscapeUriString
。
"https://www.google.com/?q=happy c++"
。「?」で手動で分割する必要があるようですが、もっと良い方法はありますか?
EscapeDataString
。指定したURLが実際のURLである場合、はい、そのまま分割し?
ます。
ソース内のコメントは、違いを明確に示しています。なぜこの情報がXMLドキュメントのコメントを介して提供されないのかは、私には謎です。
EscapeUriString:
このメソッドは、パーセント記号を含め、予約済みまたは未予約の文字ではない文字をエスケープします。EscapeUriStringも「#」記号をエスケープしないことに注意してください。
EscapeDataString:
このメソッドは、パーセント記号など、予約されていない文字以外の文字をエスケープします。
したがって、違いは、予約文字の処理方法にあります。EscapeDataString
それらをエスケープします。EscapeUriString
ではない。
RFCによれば、予約文字は次のとおりです。:/?#[]@!$&'()*+,;=
完全を期すため、予約されていない文字は英数字と -._~
どちらの方法でも、予約済みでも予約済みでもない文字をエスケープします。
私は一般的に反対概念EscapeUriString
悪です。予約文字ではなく、不正な文字(スペースなど)のみをエスケープする方法が便利だと思います。しかし、それはそれがキャラクターを処理する方法に奇妙な点を持っています。パーセントエンコードされた文字(その後に2桁の16進数)は、URIで有効です。このパターンが検出され、すぐに2桁の16進数が続く場合はエンコードを回避すると、はるかに役立つと思います。%
%
EscapeUriString
%
簡単な例
var data = "example.com/abc?DEF=あいう\x20えお";
Console.WriteLine(Uri.EscapeUriString(data));
Console.WriteLine(Uri.EscapeDataString(data));
Console.WriteLine(System.Net.WebUtility.UrlEncode(data));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(data));
/*
=>
example.com/abc?DEF=%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86+%E3%81%88%E3%81%8A
example.com%2fabc%3fDEF%3d%e3%81%82%e3%81%84%e3%81%86+%e3%81%88%e3%81%8a
*/
Uri.EscapeDataString()
ます。他のアプローチでは、システムはすべての可能な入力に対して意図された結果を生成するのに十分な情報を持っていません。