如何在WCF SOAP方法上实现curl GET
本文关键字:实现 curl GET 方法 SOAP WCF | 更新日期: 2023-09-27 18:11:01
我有一个使用WCF的服务,在SLES盒子上运行Mono。我用的是BasicHttpBinding。现在,我有一个简单地返回布尔值的方法,我想从SLES框本身调用这个方法并获取布尔值。我正在尝试使用curl,但到目前为止,我还没有成功调用该方法。
假设我的服务名为"RemoteService",我想调用的方法是"CheckProcessRunning"。同样,CheckProcessRunning只是返回一个布尔值,而且返回得非常快。
所以我试过:
curl -H "Content-Type: text/xml; charset=utf-8" -H "SOAPAction:" -X GET http://localhost:4000/RemoteService/CheckProcessRunning
curl --header "Content-Type: text/xml;charset=UTF-8" --header "SOAPAction:RemoteService/CheckProcessRunning" http://localhost:4000/RemoteService/CheckProcessRunning
curl --header "Content-Type: text/xml;charset=UTF-8" --header "SOAPAction:url:CheckProcessRunning" http://localhost:4000/RemoteService
都返回如下内容:
<?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><s:Fault><faultcode xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:DestinationUnreachable</faultcode><faultstring xml:lang="">The request message has the target 'http://localhost:4000/RemoteService/CheckProcessRunning' with action '' which is not reachable in this service contract</faultstring></s:Fault></s:Body></s:Envelope>
所以我的问题是,我如何在WCF服务中对SOAP方法进行curl请求?我需要使用BasicHttpBinding来做到这一点-我已经研究了WebHttpBinding,但我发现我不能使用它,因为它破坏了其他功能。
您的帖子中的错误信息显示操作为空或为空。因此,解决方案可能是更改您的服务以支持空操作。服务将需要通过查看请求体来确定调用哪个方法。幸运的是,在WCF中有一个这样的例子。. net 4的WF示例和使用信息。
还有另一篇文章提到了cURL,并专门为这里的空操作定制了相同的示例:WCF、cURL、Java和ASMX。功劳归于原作者,但为了后人,这里是代码……
在操作契约中指定一个空操作:
[OperationContract(Action="")]
ResponseMessage DoOperationA(RequestMessage message);
[OperationContract(Action="")]
ResponseMessage DoOperationB(RequestMessage message);
为业务项目添加EmptyActionBehaviorAttribute
类:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public class EmptyActionBehaviorAttribute : Attribute, IContractBehavior
{
public void AddBindingParameters(
ContractDescription contractDescription,
ServiceEndpoint endpoint,
BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(
ContractDescription contractDescription,
ServiceEndpoint endpoint,
ClientRuntime clientRuntime)
{
return;
}
public void ApplyDispatchBehavior(
ContractDescription contractDescription,
ServiceEndpoint endpoint,
DispatchRuntime dispatchRuntime)
{
var dispatchDictionary = new Dictionary<XmlQualifiedName, string>();
foreach (var operationDescription in contractDescription.Operations)
{
var qname = new XmlQualifiedName(
operationDescription.Messages[0].Body.WrapperName,
operationDescription.Messages[0].Body.WrapperNamespace);
dispatchDictionary.Add(qname, operationDescription.Name);
}
dispatchRuntime.OperationSelector
= new EmptyActionOperationSelector(dispatchDictionary);
}
public void Validate(
ContractDescription contractDescription,
ServiceEndpoint endpoint)
{
}
}
为业务项目添加EmptyActionOperationSelector
类:
class EmptyActionOperationSelector : IDispatchOperationSelector
{
Dictionary<XmlQualifiedName, string> dispatchDictionary;
public EmptyActionOperationSelector(
Dictionary<XmlQualifiedName, string> dispatchDictionary)
{
this.dispatchDictionary = dispatchDictionary;
}
public string SelectOperation(ref System.ServiceModel.Channels.Message message)
{
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(message.ToString());
var nsManager = new XmlNamespaceManager(xmlDoc.NameTable);
nsManager.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
XmlNode node = xmlDoc.SelectSingleNode(
"/soapenv:Envelope/soapenv:Body",
nsManager).FirstChild;
var lookupQName = new XmlQualifiedName(node.LocalName, node.NamespaceURI);
return dispatchDictionary.ContainsKey(lookupQName)
? dispatchDictionary[lookupQName]
: node.LocalName;
}
}
最后,在服务契约上使用新属性:
[ServiceContract]
[XmlSerializerFormat(Style = OperationFormatStyle.Rpc, Use = OperationFormatUse.Encoded)]
[EmptyActionBehavior]
public interface IMyService
下面是它的工作原理:
我向WCF接口添加了WebInvoke装饰,以指定请求和响应的方法和格式:
[OperationContract]
[WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
bool CheckProcessRunning();
我还初始化了另一个主机(使用不同的端口),以使用WebServiceHost:
将我的接口公开为REST服务。string webHttpAddress = "http://localhost:4001/RemoteService";
WebServiceHost webServiceHost = new WebServiceHost(typeof(RemoteService), new Uri[] { new Uri(webHttpAddress) });
webServiceHost.AddServiceEndpoint(typeof(IRemoteService), new WebHttpBinding(WebHttpSecurityMode.None), webHttpAddress);
webServiceHost.Open();
现在我可以调用CheckProcessRunning方法使用curl:
curl http://localhost:4001/RemoteService/CheckProcessRunning
true