私はこれのためにキーボードに頭をぶつけました。
Yahoo GeoPlanet サービスにアクセスするために使用できるWCF クライアント プロジェクトがあります。フリーテキスト クエリのエンドポイントの 1 つは、次のように表すことができます。
[OperationContract(Name = "places")]
[WebGet(
UriTemplate = "places.q({query});count=0?format=json&view={view}&appid={appId}",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare
)]
PlacesResponse Places(string query, string appId, RequestView view);
次のように (多かれ少なかれ) WCF クライアントを呼び出すこれの実装があります: (ここには再試行ロジックがありますが、これは要約すると次のようになります)
public Places Places(string query, string appId, RequestView view = RequestView.Long)
{
return Channel.Places(HttpUtility.UrlEncode(query), appId, view);
}
問題は、query
パラメーターが URL エンコードされていても、WCF が実際の HTTP 要求を発行するまでに、 の値が%2F
スラッシュ ( /
) に変換されることです。その結果、次のような検索"Saint Augustine Tunapuna/Piarco, Trinidad and Tobago"
は (当然のことながら) Yahoo サーバーによって 400 Bad Request で拒否されています。
最悪の部分は、クライアント ライブラリが非ビジュアル スタジオ プロジェクトの参照として使用されている場合にのみ発生するように見えることです。プロジェクトには次のテストがあり、常に合格します。
[TestMethod]
public void Yahoo_GeoPlanet_GeoPlanetClient_Places_ShouldUrlEncodeQuery_WhenItContainsUnsafeCharacters()
{
using (var geoPlanetClient = new GeoPlanetClient())
{
var places = geoPlanetClient.Places("Saint Augustine Tunapuna/Piarco, Trinidad and Tobago", AppId);
places.ShouldNotBeNull();
places.Items.Count.ShouldBeInRange(1, int.MaxValue);
}
}
このライブラリを別のプロジェクトで使用すると、クライアント .csproj が他のプロジェクトのソリューションの一部であり、プロジェクト参照として参照されている場合にのみ機能します。NuGet パッケージまたは直接の dll ファイル参照として含めるとすぐに失敗します。
私はコードにステップダウンしました.URLがに渡されるまでに正しくエンコードされているようですChannel
. ただし、その後しばらくすると%2F
、検索文字列の がスラッシュに変換されます。私がこれを知っている唯一の理由は、フィドラーでリクエストを検査することです。