c# – WCF:“为MTOM消息创建阅读器时出错”
|
试图让MTOM在WCF客户端中工作.我正在尝试使用的特定函数发送一个PDF文档的MTOM编码字节数组.使用SoapUI使用WSDL测试API工作正常;但是,当我尝试在客户端中执行相同的操作时,我收到以下错误:
Error creating a reader for the MTOM message System.Xml.XmlException: MTOM messages must have type 'application/xop+xml'. at System.Xml.XmlMtomReader.ReadMessageContentTypeHeader(ContentTypeHeader he ader,String& boundary,String& start,String& startInfo) at System.Xml.XmlMtomReader.Initialize(Stream stream,String contentType,Xml DictionaryReaderQuotas quotas,Int32 maxBufferSize) at System.Xml.XmlMtomReader.SetInput(Stream stream,Encoding[] encodings,Str ing contentType,XmlDictionaryReaderQuotas quotas,Int32 maxBufferSize,OnXmlDic tionaryReaderClose onClose) at System.Xml.XmlMtomReader.SetInput(Byte[] buffer,Int32 offset,Int32 count,In t32 maxBufferSize,OnXmlDictionaryReaderClose onClose) at System.Xml.XmlDictionaryReader.CreateMtomReader(Byte[] buffer,Int32 offse t,XmlDictionaryReaderQuo tas quotas,OnXmlDictionaryReaderClose onClose) at System.ServiceModel.Channels.MtomMessageEncoder.MtomBufferedMessageData.Ta keXmlReader() Server stack trace: at System.ServiceModel.Channels.MtomMessageEncoder.MtomBufferedMessageData.Ta keXmlReader() at System.ServiceModel.Channels.BufferedMessageData.DoTakeXmlReader() at System.ServiceModel.Channels.BufferedMessageData.GetMessageReader() at System.ServiceModel.Channels.BufferedMessage..ctor(IBufferedMessageData me ssageData,RecycledMessageState recycledMessageState,Boolean[] understoodHeader s,Boolean understoodHeadersModified) at System.ServiceModel.Channels.BufferedMessage..ctor(IBufferedMessageData me ssageData,RecycledMessageState recycledMessageState) at System.ServiceModel.Channels.MtomMessageEncoder.ReadMessage(ArraySegment`1 buffer,BufferManager bufferManager,String contentType) at System.ServiceModel.Channels.MessageEncoder.ReadMessage(Stream stream,Buf ferManager bufferManager,String contentType) at System.ServiceModel.Channels.HttpInput.ReadChunkedBufferedMessage(Stream i nputStream) at System.ServiceModel.Channels.HttpInput.ParseIncomingMessage(Exception& req uestException) at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpCha nnelRequest.WaitForReply(TimeSpan timeout) at System.ServiceModel.Channels.RequestChannel.Request(Message message,TimeS pan timeout) at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message messag e,TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.Call(String action,Boolean on eway,ProxyOperationRuntime operation,Object[] ins,Object[] outs,TimeSpan tim eout) at System.ServiceModel.Channels.ServiceChannel.Call(String action,Object[] outs) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCall Message methodCall,ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage req Msg,IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgDa ta,Int32 type) at WsApiServicePortType.getDoc(getDocRequest request) at WsApiServicePortTypeClient.WsApiServicePortType.getDoc(getDocReq uest request) in C:Usersantdocumentsvisual studio 2010ProjectsClientCl ientWsApiService.cs:line 3927 at WsApiServicePortTypeClient.getDoc(String username,String ID) in C :Usersantdocumentsvisual studio 2010ProjectsClientClientWsApiServic e.cs:line 3935 at Client.Program.Main(String[] args) in C:Usersantdocumentsvisual stu dio 2010ProjectsClientClientProgram.cs:line 18 现在,我已经搜索了所有这些错误并没有找到太多相关内容,除非是这个:http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/73039d75-e078-436b-a8ab-d8c7197a976b 但是,该链接中的建议对我没有意义.我在代码中的任何地方都看不到响应消息作为我可以修改它的对象存在.所以…我在这里.我拥有的客户端非常简单:它由svcutil生成的代理类组成,约.调用10行代码和app.config文件.我已经将证书信息添加到配置文件并将messageEncoding更改为Mtom,但除此之外,它都是由svcutil生成的. 这是客户端代码的样子(非常简单,如您所见): using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.Text;
namespace Client
{
class Program
{
static void Main(string[] args)
{
try
{
WsApiServicePortTypeClient client = new WsApiServicePortTypeClient();
byte[] doc = client.getRecordDoc("username0000","1234567");
File.WriteAllBytes(@"C:TestRecordswcf-test.pdf",doc);
Console.WriteLine("Ok,check it now.");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("ERROR: " + ex.Message + Environment.NewLine
+ ex.GetBaseException().ToString() + Environment.NewLine
+ ex.StackTrace + Environment.NewLine);
Console.ReadLine();
}
}
}
}
从代理类: [assembly: System.Runtime.Serialization.ContractNamespaceAttribute("http://www.<redacted>.com/ws/schemas",ClrNamespace="www.<redacted>.com.ws.schemas")]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel","4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://www.<redacted>.com/ws/definitions",ConfigurationName="WsApiServicePortType")]
public interface WsApiServicePortType
{
...
// CODEGEN: Generating message contract since the wrapper namespace (http://www.<redacted>.com/ws/schemas) of message getRecordDocRequest does not match the default value (http://www.<redacted>.com/ws/definitions)
[System.ServiceModel.OperationContractAttribute(Action="http://localhost:8080/getRecordDoc",ReplyAction="http://www.<redacted>.com/ws/definitions/WsApiServicePortType/getRecordDocResponse")]
[System.ServiceModel.FaultContractAttribute(typeof(www.<redacted>.com.ws.schemas.fault),Action="http://www.<redacted>.com/ws/definitions/WsApiServicePortType/getRecordDoc/Fault/wsFault",Name="fault",Namespace="http://www.<redacted>.com/ws/schemas")]
[System.ServiceModel.XmlSerializerFormatAttribute()]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(wsError))]
getRecordDocResponse getRecordDoc(getRecordDocRequest request);
...
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel","4.0.0.0")]
public partial class WsApiServicePortTypeClient : System.ServiceModel.ClientBase<WsApiServicePortType>,WsApiServicePortType
{
public WsApiServicePortTypeClient()
{
}
public WsApiServicePortTypeClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public WsApiServicePortTypeClient(string endpointConfigurationName,string remoteAddress) :
base(endpointConfigurationName,remoteAddress)
{
}
public WsApiServicePortTypeClient(string endpointConfigurationName,System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName,remoteAddress)
{
}
public WsApiServicePortTypeClient(System.ServiceModel.Channels.Binding binding,System.ServiceModel.EndpointAddress remoteAddress) :
base(binding,remoteAddress)
{
}
...
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
getRecordDocResponse WsApiServicePortType.getRecordDoc(getRecordDocRequest request)
{
return base.Channel.getRecordDoc(request);
}
public byte[] getRecordDoc(string username,string ID)
{
getRecordDocRequest inValue = new getRecordDocRequest();
inValue.username = username;
inValue.ID = ID;
getRecordDocResponse retVal = ((WsApiServicePortType)(this)).getRecordDoc(inValue);
return retVal.doc;
}
...
}
从app.config: <?xml version="1.0"?>
<configuration>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="NewBehavior0">
<clientCredentials>
<clientCertificate findValue="xxxxxxxx"
storeName="My" x509FindType="FindBySerialNumber" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="WsApiServiceSoapBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Mtom" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<security mode="Transport">
<transport clientCredentialType="Certificate" proxyCredentialType="None" realm=""/>
<message clientCredentialType="Certificate" algorithmSuite="Default"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://wisp.<redacted>.com/services/WsApiService/"
behaviorConfiguration="NewBehavior0" binding="basicHttpBinding"
bindingConfiguration="WsApiServiceSoapBinding" contract="WsApiServicePortType"
name="WsApiServicePort" />
</client>
</system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
此外,虽然我在粘贴之前将其从配置文件中删除,但我已将其配置为用于消息跟踪和日志记录,这是记录的内容: 出站: <MessageLogTraceRecord> <HttpRequest xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace"> <Method>POST</Method> <QueryString></QueryString> <WebHeaders> <VsDebuggerCausalityData>gibberish</VsDebuggerCausalityData> </WebHeaders> </HttpRequest> <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://localhost:8080/getRecordDoc</a:Action> <a:MessageID>urn:uuid:19966f2b-b5ed-4e30-8bd9-9180fbf527bf</a:MessageID> <ActivityId CorrelationId="9e356eb4-cbdc-407d-991b-49ed1b831037" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">95e158bd-51e7-4fe6-900b-642728f0653e</ActivityId> <a:ReplyTo> <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address> </a:ReplyTo> <a:To s:mustUnderstand="1">https://www.<redacted>.com/services/WsApiService/</a:To> </s:Header> <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <getRecordDoc xmlns="http://www.<redacted>.com/ws/schemas"> <username xmlns="">username0000</username> <ID xmlns="">1234567</ID> </getRecordDoc> </s:Body> </s:Envelope> </MessageLogTraceRecord> 以下是回复: <MessageLogTraceRecord><![CDATA[ --MIMEBoundaryurn_uuid_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Content-Type: text/xml; charset=UTF-8 Content-Transfer-Encoding: binary Content-ID: <0.urn:uuid:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@apache.org> <?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns1:getRecordDocResponse xmlns:ns1="http://www.<redacted>.com/ws/schemas"><doc><xop:Include href="cid:1.urn:uuid:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@apache.org" xmlns:xop="http://www.w3.org/2004/08/xop/include"/></doc></ns1:getRecordDocResponse></soapenv:Body></soapenv:Envelope> --MIMEBoundaryurn_uuid_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Content-Type: application/octet-stream Content-Transfer-Encoding: binary Content-ID: <1.urn:uuid:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@apache.org> %PDF-1.5 (blah blah blah Wingdings!) --MIMEBoundaryurn_uuid_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-- ]]></MessageLogTraceRecord> 跟踪日志显示“Construct ChannelFactory”和“Open ClientBase”步骤已成功完成,但是当它尝试“Process action http:// localhost:8080 / getRecordDoc时,它在启动活动边界后失败,如下所示: <E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>131075</EventID>
<Type>3</Type>
<SubType Name="Error">0</SubType>
<Level>2</Level>
<TimeCreated SystemTime="2013-06-17T19:10:31.2623643Z" />
<Source Name="System.ServiceModel" />
<Correlation ActivityID="{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}" />
<Execution ProcessName="Client.vshost" ProcessID="12040" ThreadID="10" />
<Channel />
<Computer>computer</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error">
<TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.Diagnostics.ThrowingException.aspx</TraceIdentifier>
<Description>Throwing an exception.</Description>
<AppDomain>Client.vshost.exe</AppDomain>
<Exception>
<ExceptionType>System.ServiceModel.CommunicationException,System.ServiceModel,Version=4.0.0.0,Culture=neutral,PublicKeyToken=publickeytokeninfo</ExceptionType>
<Message>Error creating a reader for the MTOM message</Message>
<StackTrace>
at System.ServiceModel.Channels.MtomMessageEncoder.MtomBufferedMessageData.TakeXmlReader()
at System.ServiceModel.Channels.BufferedMessageData.DoTakeXmlReader()
at System.ServiceModel.Channels.BufferedMessageData.GetMessageReader()
at System.ServiceModel.Channels.BufferedMessage..ctor(IBufferedMessageData messageData,Boolean[] understoodHeaders,Boolean understoodHeadersModified)
at System.ServiceModel.Channels.BufferedMessage..ctor(IBufferedMessageData messageData,RecycledMessageState recycledMessageState)
at System.ServiceModel.Channels.MtomMessageEncoder.ReadMessage(ArraySegment`1 buffer,String contentType)
at System.ServiceModel.Channels.MessageEncoder.ReadMessage(Stream stream,String contentType)
at System.ServiceModel.Channels.HttpInput.ReadChunkedBufferedMessage(Stream inputStream)
at System.ServiceModel.Channels.HttpInput.ParseIncomingMessage(Exception& requestException)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message,TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message,TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action,Boolean oneway,Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData,Int32 type)
at WsApiServicePortType.getRecordDoc(getRecordDocRequest request)
at WsApiServicePortTypeClient.WsApiServicePortType.getRecordDoc(getRecordDocRequest request)
at WsApiServicePortTypeClient.getRecordDoc(String username,String stiId)
at Client.Program.Main(String[] args)
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly,String[] args)
at System.AppDomain.nExecuteAssembly(RuntimeAssembly assembly,String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile,Evidence assemblySecurity,String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,Object state)
at System.Threading.ThreadHelper.ThreadStart()
</StackTrace>
<ExceptionString>System.ServiceModel.CommunicationException: Error creating a reader for the MTOM message ---> System.Xml.XmlException: MTOM messages must have type 'application/xop+xml'.
at System.Xml.XmlMtomReader.ReadMessageContentTypeHeader(ContentTypeHeader header,String& boundary,String& start,String& startInfo)
at System.Xml.XmlMtomReader.Initialize(Stream stream,OnXmlDictionaryReaderClose onClose)
at System.Xml.XmlMtomReader.SetInput(Byte[] buffer,OnXmlDictionaryReaderClose onClose)
at System.ServiceModel.Channels.MtomMessageEncoder.MtomBufferedMessageData.TakeXmlReader()
--- End of inner exception stack trace ---</ExceptionString>
<InnerException>
<ExceptionType>System.Xml.XmlException,System.Xml,PublicKeyToken=publickeytokeninfo</ExceptionType>
<Message>MTOM messages must have type 'application/xop+xml'.</Message>
<StackTrace>
at System.Xml.XmlMtomReader.ReadMessageContentTypeHeader(ContentTypeHeader header,String& startInfo)
at System.Xml.XmlMtomReader.Initialize(Stream stream,Int32 maxBufferSize)
at System.Xml.XmlMtomReader.SetInput(Stream stream,OnXmlDictionaryReaderClose onClose)
at System.Xml.XmlMtomReader.SetInput(Byte[] buffer,OnXmlDictionaryReaderClose onClose)
at System.Xml.XmlDictionaryReader.CreateMtomReader(Byte[] buffer,OnXmlDictionaryReaderClose onClose)
at System.ServiceModel.Channels.MtomMessageEncoder.MtomBufferedMessageData.TakeXmlReader()
</StackTrace>
<ExceptionString>System.Xml.XmlException: MTOM messages must have type 'application/xop+xml'.
at System.Xml.XmlMtomReader.ReadMessageContentTypeHeader(ContentTypeHeader header,OnXmlDictionaryReaderClose onClose)
at System.ServiceModel.Channels.MtomMessageEncoder.MtomBufferedMessageData.TakeXmlReader()</ExceptionString>
</InnerException>
</Exception>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
我认为这与合同包装器有关,如代理类文件中的CODEGEN消息所示.但是,我无法找到有关该消息的任何信息,这可以证实这一点. 任何帮助是极大的赞赏. 解决方法
更新:正如@Tone在评论中提到的那样,下面原来接受的答案是错误的.实际上,有效(并且必需)MTOM HTTP响应头的外部Content-Type具有值“multipart / related”.这是原始海报收到的标题:
Content-Type multipart/related; boundary="MIMEBoundaryurn_uuid_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"; start-info="text/xml"; type="text/xml"; start="<0.urn:uuid:xxxxxxxxxxxxxxxxxxxxxxxxxxxx@apache.org>" 真正的问题似乎是“type”属性是“text / xml”而不是“application / xop xml”. ============================================== 原始答案: 这里的Content-Type标题是“multipart / related”.这不是发送MTOM响应的正确标头,所以我认为这是服务器错误.正如例外所述,“MTOM消息必须具有(内容)类型’application / xop xml’”.尝试在服务器上对其进行硬编码,或者在某些代理中暂时更改它以查看wcf是否可行(您也可以尝试使用wcf自定义消息编码器,应该覆盖一个属性 – ContentType – 返回正确的类型).请注意,存在二进制有效负载(文件附件)标准,允许内容类型为“multipart / related”但wcf不支持它们.但是在这里消息有效负载使用标签,所以我相信服务器确实意味着发送mtom但不使用正确的内容类型标头. BTW here is an implementaion用于我为wcf提到的其他附件标准.它可能对你有用,pdf将在某些财产中提供.但另一方面,因为xml使用它可能无效,所以你可能需要在编码器中调整它.所以最好是解决服务器中的根问题. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Cocos2dx-js cc.Class的实例化
- swift -UIView的使用
- ruby-on-rails – 我如何在rails上的ruby中生成mongoid.yml
- Example: Create function in Postgresql
- ruby-on-rails – 如何删除HSTORE密钥?
- 页面里面引入优酷flash
- 带有c 17的`filesystem`在我的mac os x high sierra上不起作
- ruby-on-rails – 使用active_model_serializers序列化一组
- SQLite中如何连接字符串
- ruby-on-rails – 如何实现:with_trait使用Fabrication
