如何将 WCF 方法绑定到任意 URI

How to bind WCF methods to arbitrary URIs

我使用 WCF(通过使用 WebChannelFactory)来调用一些我无法控制的服务,这些服务是通过多种技术实现的。从 WCF 的角度来看,我的接口只有一个方法,我们称之为 "get-stuff"。因此,这些服务可以实现相同的方法 http://www.service-a.com/get-stuff, or as http://www.service-b.com/my-goodies/, or as http://www.service-c.com/retrieve-thing.php

在所有示例中,我都看到绑定到特定 URI 的方法是通过 WebGet/WebInvoke 属性的 UriTemplate 成员完成的。但这意味着 "get-stuff" 方法的所有 URI 都必须遵循固定模板。例如,我可以创建一个 UriTemplate = "/get-stuff",这样我的方法将始终绑定到 /get-stuff。

但是,我希望我的方法绑定到任意 URI。顺便说一句,参数作为 POST 数据传递,所以我不需要担心将 URI 绑定到方法的参数。

你为什么不做这样的事情

EndpointAddress endpointAddress = new EndpointAddress("any service url");
ChannelFactory<IMyService> channelFactory = new ChannelFactory<IMyService>(binding, endpointAddress);
IMyServiceclient = channelFactory.CreateChannel();
client.GetStuff();

好的,我找到了解决问题的方法,方法是在 运行 时修补 WebInvokeAttribute 的 UriTemplate。我的单一方法 WCF 接口是:

[ServiceContract]
interface IGetStuff
{
    [OperationContract]
    [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    ResponseData GetStuff(RequestData request);
}

这是我获取接口句柄的方法:

//Find the last portion of the URI path
var afterLastPathSepPos = uri.LastIndexOf('/', uri.Length - 2) + 1;
var contractDesc = ContractDescription.GetContract(typeof(IGetStuff));

foreach (var b in contractDesc.Operations[0].Behaviors)
{
    var webInvokeAttr = b as WebInvokeAttribute;

    if (webInvokeAttr != null)
    {
        //Patch the URI template to use the last portion of the path
        webInvokeAttr.UriTemplate = uri.Substring(afterLastPathSepPos, uri.Length - afterLastPathSepPos);
        break;
    }
}

var endPoint = new ServiceEndpoint(contractDesc, new WebHttpBinding(), new EndpointAddress(uri.Substring(0, afterLastPathSepPos)));

using (var wcf = new WebChannelFactory<I>(endPoint))
{
    var intf = wcf.CreateChannel();
    var result = intf.GetStuff(new RequestData(/*Fill the request data here*/));   //Voila!
}