2015-10-26 4 views
1

У меня есть клиентское приложение на C#, которое должно потреблять сторонний веб-сервис, закодированный на Java, а ответ - MTOM. Когда я использую собственный кодировщик сообщений и настраиваю basicHttpBinding, я получил ошибку «длина содержимого элемента charset ...». Ну, сторонняя служба (или контейнер веб-сервера) не отправляет кодировку, поэтому я решил создать собственный кодировщик сообщений и настраиваемую привязку для захвата ответа с веб-сервера, добавления недостающей кодировки и отправки на прикладной уровень, но когда я обрабатываю сообщение, я добавил charset, я получил сообщение об ошибке «Заголовок Content-Type из сообщения MTOM не найден».Ошибка «Заголовок Content-Type из сообщения MTOM не найден» в пользовательском кодексе сообщений C#

Вот что я maded:

Во-первых, я создал несколько классов для работы с сообщением:
- CustomMtomBindingElementExtensionElement простирающуюся BindingElementExtensionElement
- CustomMtomMessageEncodingBindingElement расширения MessageEncodingBindingElement и реализации IWsdlExportExtension
- CustomMtomMessageEncoderFactory простирающуюся MessageEncoderFactory
- CustomMtomMessageEncoder, расширяющий MessageEncoder

В CustomMtomMessageEncoder я есть частный attributte, используемый для обработки модифицированного сообщения после добавления кодового:

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

В одном классе, я переопределяю метод 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; 
    } 

Ошибка возникает в указанной строке «Mensagem сообщения = this.mtomEncoder.ReadMessage (newBuffer, bufferManager); "

Пожалуйста, помогите.

Благодаря,

Лучано Нери

+0

Я столкнулся с тем же, что я заметил, так это то, что вызванный WCF запрос MTOM имеет это в боде. MIME-версия: 1.0 Content-Type: multipart/related; type = "application/xop + xml"; border = "9a7b8f09-41a7-4cf9-b3a8-0e490e38890e + id = 6"; start = "";start-info="application/soap+xml " Что я думаю, что пытается найти кодер mtom. – MichaelChan

ответ

0

Решение этой проблемы состоит в добавлении тип содержимого (который является частью параметров ReadMessage) в начало массива байтов перед вызовом InnerEncoder.ReadMessage. Это Microsoft WCF не соответствует стандартам SOAP. Имейте в виду, что я использую VS2015. 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; 
+0

Я добавил тип контента в сообщение, но не так, как вы предложили, можете ли вы отправить пример, пожалуйста? –

+0

Преобразование типа содержимого в байты [] (http: // stackoverflow.com/questions/16072709/converting-string-to-byte-array-in-c-sharp), затем объедините буфер.Array (http://stackoverflow.com/questions/415291/best-way-to-combine-two -или- больше-байтовые-массивы-в-с-диез) – MichaelChan

0

Этот вопрос очень старый, но все же я хотел бы ответить на него, потому что там может быть еще несколько госзакупок ищет ответ:

Вам нужно передать строку CONTENTTYPE в mtomEncoder. Функция ReadMessage. Чем это будет работать.

Если вы изменили больше в своей функции ReadMessage, возможно, вам придется изменить то же самое в contentTypestring - но не беспокойтесь, вы получите чистое исключение, которое поможет вам исправить вашу проблему.