简体   繁体   English

自定义消息编码器c#中的错误“找不到来自MTOM消息的Content-Type标头”

[英]Error “Content-Type header from MTOM message not found” in custom message encoder c#

I have a client application in C# that needs to consume a third party web service coded in Java, and the response is MTOM. 我在C#中有一个客户端应用程序,需要使用Java编码的第三方Web服务,并且响应是MTOM。 When I uses native message encoder and configure basicHttpBinding, I receivced error "the content length of charset element...". 当我使用本机消息编码器并配置basicHttpBinding时,收到错误“字符集元素的内容长度...”。 Well, the third party service (or the web server container) is not sending the charset, so I decided to create a custom message encoder and custom binding for to capture the response from web server, adds missing charset and send to application layer, but when i process the message I added charset, I received an error "Content-Type header from MTOM message not found". 好了,第三方服务(或Web服务器容器)没有发送字符集,因此我决定创建一个自定义消息编码器和自定义绑定,以捕获来自Web服务器的响应,添加缺少的字符集并发送到应用程序层,但是当我处理添加字符集的消息时,收到错误消息“找不到MTOM消息中的Content-Type标头”。

Here is what I maded: 这是我所做的:

First, I have created some classes to work with message: 首先,我创建了一些用于处理消息的类:
- CustomMtomBindingElementExtensionElement extending BindingElementExtensionElement -CustomMtomBindingElementExtensionElement扩展BindingElementExtensionElement
- CustomMtomMessageEncodingBindingElement extending MessageEncodingBindingElement and implementing IWsdlExportExtension -CustomMtomMessageEncodingBindingElement扩展MessageEncodingBindingElement并实现IWsdlExportExtension
- CustomMtomMessageEncoderFactory extending MessageEncoderFactory -CustomMtomMessageEncoderFactory扩展MessageEncoderFactory
- CustomMtomMessageEncoder extending MessageEncoder -CustomMtomMessageEncoder扩展MessageEncoder

In CustomMtomMessageEncoder i have a private attributte used to process the modified message after add charset: 在CustomMtomMessageEncoder中,我有一个私有属性,用于在添加字符集后处理修改后的消息:

public class CustomMtomMessageEncoder : MessageEncoder
{
    private MessageEncoder mtomEncoder;
    private CustomMtomMessageEncoderFactory factory;
    private XmlWriterSettings writerSettings;
    private string contentType;

    public CustomMtomMessageEncoder(CustomMtomMessageEncoderFactory factory)
    {
        this.factory = factory;
        this.writerSettings = new XmlWriterSettings();
        this.contentType = string.Format("{0}; charset={1}", this.factory.MediaType, this.writerSettings.Encoding.HeaderName);

        MtomMessageEncodingBindingElement mtomBindingElement = new MtomMessageEncodingBindingElement(this.MessageVersion, Encoding.GetEncoding(this.factory.CharSet));

        this.factory.ReaderQuotas.CopyTo(mtomBindingElement.ReaderQuotas);
        this.mtomEncoder = mtomBindingElement.CreateMessageEncoderFactory().Encoder;
    }

    //Other things...
}

In same class, i overrides ReadMessage method: 在同一个类中,我重写ReadMessage方法:

    public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
    {
        //Convert the received buffer into a string
        byte[] incomingResponse = buffer.Array;

        //read the first 500 bytes of the response
        string strFirst500 = System.Text.Encoding.UTF8.GetString(incomingResponse, 0, 500);

        //Check the last occurance of 'application/xop+xml' in the response. We check for the last
        //occurrence since the first one is present in the Content-Type HTTP Header. Once found,
        //append charset header to this string
        int appIndex = strFirst500.LastIndexOf("application/xop+xml");
        string modifiedResponse = strFirst500.Insert(appIndex + 19, "charset=utf-8");

        modifiedResponse = modifiedResponse.Replace("application/xop+xmlcharset=utf-8", "application/xop+xml; charset=utf-8");

        //convert the modified string back into a byte array
        byte[] ma = System.Text.Encoding.UTF8.GetBytes(modifiedResponse);

        //integrate the modified byte array back to the original byte array
        int increasedLength = ma.Length - 500;
        byte[] newArray = new byte[incomingResponse.Length + increasedLength];

        for (int count = 0; count < newArray.Length; count++)
        {
            if (count < ma.Length)
            {
                newArray[count] = ma[count];
            }
            else
            {
                newArray[count] = incomingResponse[count - increasedLength];
            }
        }

        //In this part generate a new ArraySegment<byte> buffer and pass it to the underlying MTOM Encoder.
        ArraySegment<byte> newBuffer = new ArraySegment<byte>(newArray);

        /*##### Here the error is triggered with message "can not create mtom reader for message" and inner exception is "Content-Type header from mtom message not found" #####*/
        Message mensagem = this.mtomEncoder.ReadMessage(newBuffer, bufferManager);

        return mensagem;
    }

The error occurs in indicated line "Message mensagem = this.mtomEncoder.ReadMessage(newBuffer, bufferManager);" 错误发生在指示的行“消息mensagem = this.mtomEncoder.ReadMessage(newBuffer,bufferManager);”中

Please help. 请帮忙。

Thanks, 谢谢,

Luciano Nery 卢西亚诺·纳里(Luciano Nery)

The solution to this is to append the content type (which is part of ReadMessage parameters) to the beginning of the byte array before calling InnerEncoder.ReadMessage. 解决方案是在调用InnerEncoder.ReadMessage之前,将内容类型(属于ReadMessage参数的一部分)附加到字节数组的开头。 This is Microsoft WCF not complying with SOAP standards. 这是Microsoft WCF不符合SOAP标准。 Mind that I'm using VS2015. 请注意,我正在使用VS2015。 bytesToEncode is the buffer.Array. bytesToEncode是buffer.Array。

const string ContentTypeHeader = "content-type";
var encoding = new UTF8Encoding(false);
var header = $"{ContentTypeHeader}: {headerValue}{Environment.NewLine}";
var headerBytes = encoding.GetBytes(header);

var contentWithHeader = new byte[headerBytes.Length + bytesToEncode.Length];
Buffer.BlockCopy(headerBytes, 0, contentWithHeader, 0, headerBytes.Length);
Buffer.BlockCopy(bytesToEncode, 0, contentWithHeader, headerBytes.Length, bytesToEncode.Length);
return contentWithHeader;

This question is very old, but still i'd like to answer it, because there might be some more ppl looking for an answer: 这个问题很老,但是我仍然想回答,因为可能会有更多的人在寻找答案:

You need to pass the contentType string to the mtomEncoder.ReadMessage function. 您需要将contentType字符串传递给mtomEncoder.ReadMessage函数。 Than it will work. 比它会工作。

In case you changed more in your ReadMessage function you might have to change the same things in the contentTypestring - but dont worry, you will receive a clean exception which will help you to fix your problem. 如果您在ReadMessage函数中进行了更多更改,则可能必须更改contentTypestring中的相同内容-但不用担心,您将收到一个干净的异常,它将帮助您解决问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 WCF自定义编码器-在运行时分配消息内容类型 - WCF Custom encoder - Assigning message content type at runtime C# 带有自定义标头的 HttpClient POST 请求发送不正确的 Content-Type header 字段 - C# HttpClient POST Request with Custom Headers sends incorrect Content-Type header field 无法使用c#HttpClient发送Content-Type标头 - Can't send Content-Type header with c# HttpClient C#:在HTTP中使用Content-Type标头发送参数 - C#: Sending parameter with Content-Type Header in HTTP 为 WCF 消息设置 HTTP 内容类型 - Setting HTTP content-type for WCF message 如何将Content-Length,Content-Type和Last-Modified添加到HTTP响应消息头中 - How to add the Content-Length,Content-Type and Last-Modified to the HTTP Response Message Header 找不到使用Content-ID&#39;&lt;858d8f9f-b101-46c3-bf84-d2b934ad1271&gt;&#39;的MTOM消息MIME部分创建阅读器的错误 - Error creating a reader for the MTOM message MIME part with Content-ID '<858d8f9f-b101-46c3-bf84-d2b934ad1271>' not found MTOM - 在VS 2010中读取时遇到无效的MIME内容类型标头 - MTOM - Invalid MIME content-type header encountered on read in VS 2010 C# HttpClient,出现错误无法添加值,因为标头“内容类型”不支持多个值 - C# HttpClient, getting error Cannot add value because header 'content-type' does not support multiple values 如何从C#向Ajax发送错误消息以在客户端使用此错误消息的内容? - How to send error message from C# to Ajax to use this error message's content in client side?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM