WCF: "Error creating reader for MTOM message"

An attempt to get MTOM to work in the WCF client. The particular function I'm trying to use sends an array of bytes encoded in the MTOM of the PDF. Using SoapUI to test the API using WSDL works fine; however, when I try to do the same in the client, I get the following error:

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 , Encoding[] encodings, String contentType, XmlDictionaryReaderQuotas quotas, In t32 maxBufferSize, OnXmlDictionaryReaderClose onClose) at System.Xml.XmlDictionaryReader.CreateMtomReader(Byte[] buffer, Int32 offse t, Int32 count, Encoding[] encodings, String contentType, XmlDictionaryReaderQuo tas quotas, Int32 maxBufferSize, 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, Int32 maxBufferSize, 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, Boolean on eway, ProxyOperationRuntime operation, Object[] ins, 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:\Users\ant\documents\visual studio 2010\Projects\Client\Cl ient\WsApiService.cs:line 3927 at WsApiServicePortTypeClient.getDoc(String username, String ID) in C :\Users\ant\documents\visual studio 2010\Projects\Client\Client\WsApiServic e.cs:line 3935 at Client.Program.Main(String[] args) in C:\Users\ant\documents\visual stu dio 2010\Projects\Client\Client\Program.cs:line 18 

Now I searched everything and cannot find much for this error, except maybe this one: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/73039d75-e078-436b-a8ab- d8c7197a976b

The recommendation in this link, however, makes no sense to me. I do not see anywhere in my code where the response message exists as an object where I could modify it. And here I am. The client I have is extremely simple: it consists of a proxy class created by svcutil, approx. 10 lines of code to call and the app.config file. I added the certificate information to the configuration file and changed messageEncoding to Mtom, but apart from that, it is all svcutil-generated.

Here's the client code (very simple, as you can see):

 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:\TestRecords\wcf-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(); } } } } 

From the proxy class:

 [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; } ... } 

And from 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> 

In addition, although I cut it from the configuration file before pasting, I configured it to trace and log messages, and here's what gets logged:

Outbound:

 <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> 

And here is the answer:

 <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> 

The trace log shows that the “Construct ChannelFactory” and “Open ClientBase” steps complete successfully, but when it tries “Process action http://localhost:8080/getRecordDoc , it does not work after starting the action border as follows:

 <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, RecycledMessageState recycledMessageState, Boolean[] understoodHeaders, Boolean understoodHeadersModified) at System.ServiceModel.Channels.BufferedMessage..ctor(IBufferedMessageData messageData, RecycledMessageState recycledMessageState) at System.ServiceModel.Channels.MtomMessageEncoder.ReadMessage(ArraySegment`1 buffer, BufferManager bufferManager, String contentType) at System.ServiceModel.Channels.MessageEncoder.ReadMessage(Stream stream, BufferManager bufferManager, Int32 maxBufferSize, String contentType) at System.ServiceModel.Channels.HttpInput.ReadChunkedBufferedMessage(Stream inputStream) at System.ServiceModel.Channels.HttpInput.ParseIncomingMessage(Exception&amp; 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, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, 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&amp; 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, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() </StackTrace> <ExceptionString>System.ServiceModel.CommunicationException: Error creating a reader for the MTOM message ---&gt; System.Xml.XmlException: MTOM messages must have type 'application/xop+xml'. at System.Xml.XmlMtomReader.ReadMessageContentTypeHeader(ContentTypeHeader header, String&amp; boundary, String&amp; start, String&amp; startInfo) at System.Xml.XmlMtomReader.Initialize(Stream stream, String contentType, XmlDictionaryReaderQuotas quotas, Int32 maxBufferSize) at System.Xml.XmlMtomReader.SetInput(Stream stream, Encoding[] encodings, String contentType, XmlDictionaryReaderQuotas quotas, Int32 maxBufferSize, OnXmlDictionaryReaderClose onClose) at System.Xml.XmlMtomReader.SetInput(Byte[] buffer, Int32 offset, Int32 count, Encoding[] encodings, String contentType, XmlDictionaryReaderQuotas quotas, Int32 maxBufferSize, OnXmlDictionaryReaderClose onClose) at System.Xml.XmlDictionaryReader.CreateMtomReader(Byte[] buffer, Int32 offset, Int32 count, Encoding[] encodings, String contentType, XmlDictionaryReaderQuotas quotas, Int32 maxBufferSize, OnXmlDictionaryReaderClose onClose) at System.ServiceModel.Channels.MtomMessageEncoder.MtomBufferedMessageData.TakeXmlReader() --- End of inner exception stack trace ---</ExceptionString> <InnerException> <ExceptionType>System.Xml.XmlException, System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=publickeytokeninfo</ExceptionType> <Message>MTOM messages must have type 'application/xop+xml'.</Message> <StackTrace> at System.Xml.XmlMtomReader.ReadMessageContentTypeHeader(ContentTypeHeader header, String&amp; boundary, String&amp; start, String&amp; startInfo) at System.Xml.XmlMtomReader.Initialize(Stream stream, String contentType, XmlDictionaryReaderQuotas quotas, Int32 maxBufferSize) at System.Xml.XmlMtomReader.SetInput(Stream stream, Encoding[] encodings, String contentType, XmlDictionaryReaderQuotas quotas, Int32 maxBufferSize, OnXmlDictionaryReaderClose onClose) at System.Xml.XmlMtomReader.SetInput(Byte[] buffer, Int32 offset, Int32 count, Encoding[] encodings, String contentType, XmlDictionaryReaderQuotas quotas, Int32 maxBufferSize, OnXmlDictionaryReaderClose onClose) at System.Xml.XmlDictionaryReader.CreateMtomReader(Byte[] buffer, Int32 offset, Int32 count, Encoding[] encodings, String contentType, XmlDictionaryReaderQuotas quotas, Int32 maxBufferSize, 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, String&amp; boundary, String&amp; start, String&amp; startInfo) at System.Xml.XmlMtomReader.Initialize(Stream stream, String contentType, XmlDictionaryReaderQuotas quotas, Int32 maxBufferSize) at System.Xml.XmlMtomReader.SetInput(Stream stream, Encoding[] encodings, String contentType, XmlDictionaryReaderQuotas quotas, Int32 maxBufferSize, OnXmlDictionaryReaderClose onClose) at System.Xml.XmlMtomReader.SetInput(Byte[] buffer, Int32 offset, Int32 count, Encoding[] encodings, String contentType, XmlDictionaryReaderQuotas quotas, Int32 maxBufferSize, OnXmlDictionaryReaderClose onClose) at System.Xml.XmlDictionaryReader.CreateMtomReader(Byte[] buffer, Int32 offset, Int32 count, Encoding[] encodings, String contentType, XmlDictionaryReaderQuotas quotas, Int32 maxBufferSize, OnXmlDictionaryReaderClose onClose) at System.ServiceModel.Channels.MtomMessageEncoder.MtomBufferedMessageData.TakeXmlReader()</ExceptionString> </InnerException> </Exception> </TraceRecord> </DataItem> </TraceData> </ApplicationData> </E2ETraceEvent> 

I think this has something to do with the shell of the contract, as indicated in the CODEGEN messages in the proxy class file. I can’t find anything about this post, but this will confirm it.

Any help is greatly appreciated.

+4
source share
2 answers

UPDATE: As @Tone mentions in the comments, the original accepted answer below is incorrect. It is really valid (and necessary) for the external Content-Type of the MTOM HTTP response header in order to have the value "multipart / related". This is the title that the original poster received:

 Content-Type multipart/related; boundary="MIMEBoundaryurn_uuid_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"; start-info="text/xml"; type="text/xml"; start="<0.urn:uuid: xxxxxxxxxxxxxxxxxxxxxxxxxxxx@apache.org >" 

The real problem seems to be that the "type" attribute is "text / xml" and not "application / xop + xml".

================================================

Original answer:

The Content-Type header is here "multipart / related". This is the wrong header for sending an MTOM response, so I believe this is a server error. As the exception mentions, “MTOM messages should have (content) of type“ application / xop + xml. ”Try hard-coding it on the server or temporarily changing it in some proxy server to see that wcf will work (you can also to try the wcf user message encoder, it should override one property - ContentType - to return to the right.) Note that there are binary payload (file) standards that allow the content type "multipart / related", but wcf does not support them. However, here is useful load reported I use the tag, so I believe the server means send mtom, but does not use the correct header for the content content.

BTW here is an implementation for another binding standard that I mentioned for wcf. it may work for you, pdf will be available in any property. but on the other hand, since xml uses it, it may not be valid, so you may need to configure it in the encoder anyway. therefore, it is best to solve the root problem on the server.

+1
source

In my case, I got the indicated error, in my binding I had

 maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" 

it did not start working until I added:

 maxBufferSize="2147483647" 

You just have the same problem.

0
source

Source: https://habr.com/ru/post/1486882/


All Articles