简体   繁体   中英

Strange behavior with WCF WebGetAttribute's UriTemplate property

I'm done banging my head on the keyboard for this one.

I have a WCF client project that can be used to hit the Yahoo GeoPlanet service. One of their endpoints for free-text querying can be represented like so:

[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);

There is an implementation of this that invokes the WCF client (more or less) like so: (there is retry logic here, but this is what it boils down to)

public Places Places(string query, string appId, RequestView view = RequestView.Long)
{
    return Channel.Places(HttpUtility.UrlEncode(query), appId, view);
}

The problem is that, even though the query parameter is url encoded, by the time WCF issues the actual HTTP request, values of %2F are converted back into a forward slash ( / ). As a result, searches like "Saint Augustine Tunapuna/Piarco, Trinidad and Tobago" are (understandably) being rejected with a 400 Bad Request by the Yahoo server.

The worst part of it is that this only seems to happen when the client library is used as a non-visual studio project reference. I have the following test in the project, which always passes:

[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);
    }
}

When I use this library in another project, it works only when the client .csproj is part of the other project's solution, and is referenced as a project reference. As soon as I include it as a NuGet package or direct dll file reference, it fails.

I have stepped down into the code, and it seems like the URL is correctly encoded by the time it is passed to the Channel . However sometime after that, the %2F in the search string is getting converted back into a forward slash. The only reason I know this is from inspecting the request in fiddler.

Perhaps consider using HttpClient ? It's a LOT simpler.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM