如何将 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!
}
我使用 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!
}