You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WCF服务接收MTOM附件POST请求报错:创建MTOM消息读取器失败

WCF MTOM服务接收请求返回400 Bad Request的排查与解决

问题背景

开发了一个WCF服务,用于接收带MTOM文件附件的SOAP POST请求,服务契约及实现代码如下:

[ServiceContract(Namespace = "http://example.com/schema/service/Upload/1.0")]
[XmlSerializerFormat]
public interface IBillerReconcileNotificationService
{
    [OperationContract(Action = "Reconcile")]
    [FaultContract(typeof(BillerNotificationFault))]
    UploadMsgRs Reconcile(UploadMsgRq requestModel);
}

public class BillerReconcileNotificationService : IBillerReconcileNotificationService
{ 
    public UploadMsgRs Reconcile(UploadMsgRq requestModel)
    {//处理请求业务逻辑}
}

使用Postman测试时,服务始终返回400 Bad Request,WCF跟踪日志抛出异常:

<Exception>
<ExceptionType>System.ServiceModel.CommunicationException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>Error creating a reader for the MTOM message</Message>
<StackTrace>
at System.ServiceModel.Channels.MtomMessageEncoder.MtomBufferedMessageData.TakeXmlReader()
at System.ServiceModel.Channels.BufferedMessageData.GetMessageReader()
at System.ServiceModel.Channels.BufferedMessage..ctor(IBufferedMessageData messageData, RecycledMessageState recycledMessageState, Boolean[] understoodHeaders, Boolean understoodHeadersModified)
at System.ServiceModel.Channels.MtomMessageEncoder.ReadMessage(ArraySegment`1 buffer, BufferManager bufferManager, String contentType)
at System.ServiceModel.Channels.HttpInput.DecodeBufferedMessage(ArraySegment`1 buffer, Stream inputStream)
at System.ServiceModel.Channels.HttpInput.ParseMessageAsyncResult.ContinueReading(Int32 bytesRead)
at System.ServiceModel.Channels.HttpInput.ParseMessageAsyncResult.DecodeBufferedMessageAsync()
at System.ServiceModel.Channels.HttpInput.ParseMessageAsyncResult.BeginParse()
at System.ServiceModel.Channels.HttpInput.BeginParseIncomingMessage(HttpRequestMessage httpRequestMessage, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginParseIncomingMessage(AsyncCallback asynCallback, Object state)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult..ctor(ReplyChannelAcceptor acceptor, Action dequeuedCallback, HttpPipeline pipeline, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync()
at System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
at System.ServiceModel.AspNetPartialTrustHelpers.PartialTrustInvoke(ContextCallback callback, Object state)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequestWithFlow(Object state)
at System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.ServiceModel.CommunicationException: Error creating a reader for the MTOM message ---> System.Xml.XmlException: Root MIME part containing infoset not found.
   at System.Xml.XmlMtomReader.ReadRootMimePart()
   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.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=b77a5c561934e089</ExceptionType>
<Message>Root MIME part containing infoset not found.</Message>
<StackTrace>
at System.Xml.XmlMtomReader.ReadRootMimePart()
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.ServiceModel.Channels.MtomMessageEncoder.MtomBufferedMessageData.TakeXmlReader()
</StackTrace>
<ExceptionString>System.Xml.XmlException: Root MIME part containing infoset not found.
   at System.Xml.XmlMtomReader.ReadRootMimePart()
   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.ServiceModel.Channels.MtomMessageEncoder.MtomBufferedMessageData.TakeXmlReader()</ExceptionString>
</InnerException>
</Exception>

请求头的Content-Type为:
multipart/related; boundary=3f9d206f-1054-4731-b737-6e724723832a; start-info="text/xml"; type="application/xop+xml"

服务采用basicHttpBinding并启用MTOM,配置如下:

<system.serviceModel>
<services>
<service name="BPNotificationWeb.Services.BillerReconcileNotificationService" behaviorConfiguration="ReconcileHttpBindingBehavior">
                <endpoint address="" binding="basicHttpBinding"
                          contract="BPNotificationWeb.Services.IBillerReconcileNotificationService"
                          bindingConfiguration="httpBinding"
                </endpoint>
            </service>
</services>
<bindings>
<basicHttpBinding>
<binding name="httpBinding"  messageEncoding="Mtom" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647"></binding>
</basicHttpBinding>
</bindings>
        <behaviors>
            <serviceBehaviors>
                <behavior name="BillerNotificationHttpBindingBehavior">
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                </behavior>
            </serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>

解决建议

1. 修正服务配置的行为名称不匹配问题

服务节点的behaviorConfiguration指定为ReconcileHttpBindingBehavior,但behaviors节点下定义的行为名称是BillerNotificationHttpBindingBehavior,两者不匹配。修改服务节点的行为配置名称:

<service name="BPNotificationWeb.Services.BillerReconcileNotificationService" behaviorConfiguration="BillerNotificationHttpBindingBehavior">

2. 确保Postman请求的MTOM格式符合规范

异常提示Root MIME part containing infoset not found,说明请求的MIME结构不符合MTOM要求:

  • SOAP信封必须作为第一个MIME部分(Root MIME part),该部分的Content-Type需设置为application/xop+xml
  • 附件部分需通过cid:引用关联到SOAP信封中的对应元素
  • 若请求头指定了start参数,必须与SOAP部分的Content-ID一致;未指定时,默认第一个MIME部分为Root

3. 验证数据契约的MTOM支持

确保UploadMsgRq中接收附件的字段标记了正确的特性(如[MessageMember]或[XmlElement]),类型为Stream或byte[],同时确认数据契约与SOAP信封的映射关系正确。

4. 补充绑定的readerQuotas配置

在basicHttpBinding中添加readerQuotas配置,避免因数据大小限制导致解析失败:

<binding name="httpBinding"  messageEncoding="Mtom" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
  <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" 
                maxArrayLength="2147483647" maxBytesPerRead="2147483647" 
                maxNameTableCharCount="2147483647" />
</binding>

5. 用WCF客户端生成工具验证请求格式

通过SvcUtil.exe生成客户端代码,调用服务并抓取正确的MTOM请求格式,对比Postman构造的请求,排查格式差异。


内容的提问来源于stack exchange,提问作者Voice Of The Rain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 21:01:05