我们正在尝试访问一个 web 服务(我相信它也是使用 WCF 编码的,但我无法控制它)并且我得到一个异常:
System.ServiceModel.FaultException:WSE012:输入不是有效的 SOAP 消息,因为缺少以下信息:操作。
服务器堆栈跟踪:
at System.ServiceModel.Channels.ServiceChannel.HandleReply(
ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action,
Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs,
TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(
IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
在 [0] 处重新抛出异常:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(
IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(
MessageData& msgData, Int32 type)
at ClientName.ProjectName.Services.ServiceName.ServiceNameSoap.CallServiceName(
Request request)
at ClientName.ProjectName.Scheduler.ThirdPartyName.ProcessServiceName.Execute(
Object state) in ...\ProcessServiceName.cs:line 65
调用代码ProcessServiceName.Execute
如下:
Request serviceRequest = request.BuildServiceRequest();
Result result = client.CallServiceName(serviceRequest);
LogServiceErrors(db, request.ServiceNameRequestId, result.errors);
异常来自第二行,它直接调用服务引用自动生成的 WCF 代码,调用; 该方法只获取数据库对象并将其转换为 Web 服务所需的对象。System.ServiceModel.ClientBase<T>. Channel
.CallServiceName(request)
BuildServiceRequest
App.config
(这在 Windows 服务中调用)的相关部分内容如下:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="webBinding">
</binding>
</webHttpBinding>
<wsHttpBinding>
<binding name="ThirdPartySoap" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00"
sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536" messageEncoding="Text"
textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192"
maxArrayLength="16384" maxBytesPerRead="4096"
maxNameTableCharCount="16384"/>
<security mode="Transport">
<transport clientCredentialType="Basic" proxyCredentialType="None"
realm="www.serviceprovider.com"/>
<message clientCredentialType="UserName"
algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint name="ServiceNameSoap"
address="https://www.serviceprovider.com/ServiceName.asmx"
binding="wsHttpBinding" bindingConfiguration="ThirdPartySoap"
contract="ServiceName.ServiceNameSoap"/>
</client>
</system.serviceModel>
鉴于执行实际 web 服务工作的所有代码都来自 WCF,我不太明白问题出在哪里,但大概我需要一些稍微不同的东西App.config
来防止它。
看过Google后,我没有找到任何帮助。在 StackOverflow 上,2011 年 9 月的这个未回答的 WCF 问题没有任何帮助;自定义绑定(2009 年 11 月的回答和关于 WSE 的链接)没有帮助(我几乎不理解它们),2009 年 11 月的论坛回答和 2009 年10月的 ColdFusion 事情都无关。我看到的所有其他谷歌点击都是这些链接的副本。
任何帮助将不胜感激!
编辑以添加更多细节
Wiktor Zychla正确地指出问题可能(理论上)出在代理类中。但是,这些类是完全未经自动生成的类编辑的;例如:
using System.CodeDom.Compiler;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace ClientName.ProjectName.Services.ServiceName
{
[GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface ServiceNameSoapChannel : ServiceNameSoap, IClientChannel {}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class ServiceNameSoapClient : ClientBase<ServiceNameSoap>,
ServiceNameSoap
{
public ServiceNameSoapClient() { }
public ServiceNameSoapClient(string endpointConfigurationName) :
base(endpointConfigurationName) { }
public ServiceNameSoapClient(string endpointConfigurationName,
string remoteAddress) :
base(endpointConfigurationName, remoteAddress) { }
public ServiceNameSoapClient(string endpointConfigurationName,
EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress) { }
public ServiceNameSoapClient(Binding binding,
EndpointAddress remoteAddress) : base(binding, remoteAddress) { }
public Result CallServiceName(Request request)
{ return base.Channel.CallServiceName(request); }
}
}
所有其他代理类同样未从自动生成的代码中编辑(我在此处为空白和命名空间优化进行了编辑,以便它更适合 StackOverflow 中的屏幕;我为其添加using
语句的三个命名空间在所有方面都是完全合格的类引用,就像我ClientName.ProjectName.Services.ServiceName
在这些示例中编辑的命名空间一样。
添加WCF Message Logging后,我在消息日志中得到以下信息。(这是来自与上面代码不同的服务调用,但抛出相同的异常,部分原因是此服务调用更简单,部分原因是由于某种原因并非所有服务调用都被记录。我所做的唯一编辑是错误信息清晰易读,无需水平滚动。)
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Information">0</SubType>
<Level>8</Level>
<TimeCreated SystemTime="2013-01-18T12:00:04.7166250Z" />
<Source Name="System.ServiceModel.MessageLogging" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessName="ClientName.ProjectName.Scheduler" ProcessID="8600" ThreadID="10" />
<Channel/>
<Computer>MachineNameRedacted</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<MessageLogTraceRecord Time="2013-01-18T12:00:04.7166250+00:00" Source="TransportSend" Type="System.ServiceModel.Dispatcher.OperationFormatter+OperationFormatterMessage" xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://www.serviceprovider.com/RedactedActionName</a:Action>
<a:MessageID>urn:uuid:395d6394-5f4b-4954-8df0-8fb82d17072a</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://www.serviceprovider.com/ServiceName.asmx</a:To>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<RedactedActionName xmlns="http://www.serviceprovider.com">
<brandId>2</brandId>
</RedactedActionName>
</s:Body>
</s:Envelope>
</MessageLogTraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Information">0</SubType>
<Level>8</Level>
<TimeCreated SystemTime="2013-01-18T12:00:04.7635000Z" />
<Source Name="System.ServiceModel.MessageLogging" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessName="ClientName.ProjectName.Scheduler" ProcessID="8600" ThreadID="10" />
<Channel/>
<Computer>MachineNameRedacted</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<MessageLogTraceRecord Time="2013-01-18T12:00:04.7635000+00:00" Source="TransportReceive" Type="System.ServiceModel.Channels.BufferedMessage" xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
<env:Header xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<wsa:Action>http://schemas.xmlsoap.org/ws/2004/08/addressing/fault</wsa:Action>
<wsa:MessageID>urn:uuid:b72c6f30-8409-4b55-8c79-056d82f990a5</wsa:MessageID>
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
</env:Header>
<soap:Body>
<soap:Fault>
<soap:Code>
<soap:Value>soap:Sender</soap:Value>
</soap:Code>
<soap:Reason>
<soap:Text xml:lang="en">
WSE012: The input was not a valid SOAP message because
the following information is missing: action.
</soap:Text>
</soap:Reason>
</soap:Fault>
</soap:Body>
</soap:Envelope>
</MessageLogTraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
更多细节:ServiceNameSoap 接口
正如Wiktor Zychla所要求的,这里是ServiceNameSoap
接口声明,来自自动生成的代码,再次编辑只是为了更好地适应屏幕(因此是using
)并编辑客户机密名称:
using System.ServiceModel;
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel","4.0.0.0")]
[ServiceContractAttribute(Namespace="https://www.serviceprovider.com/",
ConfigurationName="ServiceName.ServiceNameSoap")]
public interface ServiceNameSoap
{
[OperationContractAttribute(
Action="https://www.serviceprovider.com/ServiceName",
ReplyAction="*")]
[XmlSerializerFormatAttribute(SupportFaults=true)]
[ServiceKnownTypeAttribute(typeof(ClientRequest))]
[return: MessageParameterAttribute(Name="result")]
ClientName.ProjectName.Services.ServiceName.Result CallServiceName(
ClientName.ProjectName.Services.ServiceName.Request request);
}