Ошибка при использовании веб-службы, тип содержимого "application/xop+xml" не соответствует ожидаемому типу "text/xml"

У меня странная проблема при использовании веб-сервиса для продукта, который купила моя компания. Продукт называется Campaign Commander и сделан компанией под названием Email Vision. Мы пытаемся использовать "API SOAP для массового обновления данных".

Всякий раз, когда я пытаюсь вызвать какой-либо из методов веб-службы, этот вызов на самом деле завершается успешно, но клиент обрабатывает ошибку при обработке ответа, и я получаю исключение.

Подробности ошибок ниже, спасибо за любую помощь, которую вы, ребята, можете предложить.

Ошибка при использовании веб-ссылки (старый стиль клиента веб-сервиса)

Когда я использую сервис в качестве веб-ссылки, я получаю InvalidOperationException для любого звонка, который я делаю, со следующим сообщением:

Client found response content type of 'multipart/related; type="application/xop+xml"; boundary="uuid:170e63fa-183c-4b18-9364-c62ca545a6e0"; start="<root.message@cxf.apache.org>"; start-info="text/xml"', but expected 'text/xml'.
The request failed with the error message:
--

--uuid:170e63fa-183c-4b18-9364-c62ca545a6e0
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml";
Content-Transfer-Encoding: binary
Content-ID: <root.message@cxf.apache.org>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ns2:openApiConnectionResponse xmlns:ns2="http://api.service.apibatchmember.emailvision.com/" xmlns:ns3="http://exceptions.service.apibatchmember.emailvision.com/">
      <return>DpKTe-9swUeOsxhHH9t-uLPeLyg-aa2xk3-aKe9oJ5S9Yymrnuf1FxYnzpaFojsQSkSCbJsZmrZ_d3v2-7Hj</return>
    </ns2:openApiConnectionResponse>
  </soap:Body>
</soap:Envelope>
--uuid:170e63fa-183c-4b18-9364-c62ca545a6e0--
--.

Как видите, мыльный конверт ответа выглядит корректным (это правильный ответ, и вызов выполнен успешно), но клиент, похоже, имеет проблему с типом содержимого и создает исключение.

Ошибка при использовании ссылки на службу (клиент WCF)

Когда я использую сервис в качестве справочника услуг, я получаю ProtocolException для любого звонка, который я делаю, со следующим сообщением:

The content type multipart/related; type="application/xop+xml"; boundary="uuid:af66440a-012e-4444-8814-895c843de5ec"; start="<root.message@cxf.apache.org>"; start-info="text/xml" of the response message does not match the content type of the binding (text/xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 648 bytes of the response were: '
--uuid:af66440a-012e-4444-8814-895c843de5ec
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml";
Content-Transfer-Encoding: binary
Content-ID: <root.message@cxf.apache.org>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <ns2:openApiConnectionResponse xmlns:ns2="http://api.service.apibatchmember.emailvision.com/" xmlns:ns3="http://exceptions.service.apibatchmember.emailvision.com/">
      <return>Dqaqb-MJ9V_eplZ8fPh4tdHUbxM-ZtuZsDG6GalAGZSfSzyxgtuuIxZc3aSsnhI4b0SCbJsZmrZ_d3v2-7G8</return>
    </ns2:openApiConnectionResponse>
  </soap:Body>
</soap:Envelope>
--uuid:af66440a-012e-4444-8814-895c843de5ec--'.

Как и в предыдущем примере; у нас есть действительный ответ мыла, и вызов был успешным, но у клиента, похоже, есть проблема с типом контента, и сгенерировано исключение.

Могу ли я установить какие-либо параметры, чтобы у клиента не было проблем с типом ответа? Я сделал несколько поисков в Google, но ничего, что я нашел, не помогло мне до сих пор.

7 ответов

Решение

Для тех, кто страдает от той же проблемы; Я нашел решение для использования веб-службы в качестве ссылки на службу (WCF). Для свойства BasicHttpBinding.MessageEncoding необходимо установить значение "Mtom".

Вот фрагмент обязательного параметра конфигурации:

<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding messageEncoding="Mtom">          
        </binding>
      </basicHttpBinding>
    </bindings>
  </system.serviceModel>
</configuration>

Изменить: Если у вас возникла та же проблема с пользовательской привязкой, пожалуйста, обратитесь к ответу от @robmzd.

Я до сих пор не нашел решение использовать его как веб-ссылку старого стиля.

После нескольких дней борьбы с этим я нашел удивительно простое решение этой проблемы:

  1. Активируйте Редактор конфигурации, выбрав Инструменты-> Редактор конфигурации услуг WCF в главном меню VS2010;
  2. Закройте это снова;
  3. Щелкните правой кнопкой мыши файл App.Config, чтобы найти новый пункт меню "Редактировать конфигурацию WCF";
  4. Нажмите на привязку;
  5. Измените кодировку сообщений на Mtom;
  6. Сохранить.

Надеюсь, это кому-нибудь поможет.

У меня была такая же проблема, но с <customBinding>, Чтобы это исправить, вы можете настроить Mtom Message Encoding, используя отдельный <mtomMessageEncoding> узел конфигурации под привязкой.

<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="MyServiceBinding">
          <mtomMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16" messageVersion="Soap12" writeEncoding="utf-8">
            <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
          </mtomMessageEncoding>
        </binding>
      </customBinding>
    </bindings>
  </system.serviceModel>
</configuration>

Если вы самостоятельно размещаете сервис WCF и используете сервис с клиентом WCF. Вы должны помнить, чтобы установить MessageEncoding свойство в хосте, как это:

BasicHttpBinding binding = new BasicHttpBinding();
binding.MessageEncoding = WSMessageEncoding.Mtom;

Я столкнулся с этой проблемой также. Мой клиент продолжал выдавать это исключение при запуске, и я не мог понять, почему, пока не понял, что забыл установить свои привязки MessageEncoding свойство в хост-приложении.

У меня точно такая же проблема с той же функцией и той же компанией, и я провожу пару часов в Google, пытаясь найти правильный ответ. После стольких испытаний я наконец получил это. Вот что я сделал: Следующая строка была ответом, который работает от Email Vision, где возвращал меня (моей основной целью была массовая загрузка, но я поменял местами getLastUpload для простоты и тестирования).

строка (2180)

--uuid:5c8a8a1d-a29c-43d0-baaa-cb3a8c189962
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml";
Content-Transfer-Encoding: binary
Content-ID: <root.message@cxf.apache.org>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:getLastUploadResponse xmlns:ns2="http://api.service.apibatchmember.emailvision.com/" xmlns:ns3="http://exceptions.service.apibatchmember.emailvision.com/"><return><id>254816</id><source>API_BATCH_MEMBER</source><status>DONE</status></return><return><id>254810</id><source>API_BATCH_MEMBER</source><status>DONE</status></return><return><id>254805</id><source>API_BATCH_MEMBER</source><status>DONE</status></return><return><id>254799</id><source>API_BATCH_MEMBER</source><status>DONE</status></return><return><id>254797</id><source>API_BATCH_MEMBER</source><status>DONE</status></return><return><id>254791</id><source>API_BATCH_MEMBER</source><status>DONE</status></return><return><id>254790</id><source>API_BATCH_MEMBER</source><status>DONE</status></return><return><id>254771</id><source>API_BATCH_MEMBER</source><status>DONE</status></return><return><id>254770</id><source>API_BATCH_MEMBER</source><status>ERROR</status></return><return><id>254759</id><source>API_BATCH_MEMBER</source><status>DONE</status></return><return><id>254747</id><source>API_BATCH_MEMBER</source><status>DONE</status></return><return><id>253619</id><source>CCMD</source><status>DONE</status></return><return><id>238053</id><source>CCMD</source><status>DONE WITH ERROR(S)</status></return><return><id>216618</id><source>CCMD</source><status>DONE WITH ERROR(S)</status></return><return><id>200373</id><source>CCMD</source><status>DONE</status></return><return><id>200367</id><source>CCMD</source><status>DONE</status></return><return><id>195445</id><source>CCMD</source><status>DONE</status></return><return><id>194579</id><source>CCMD</source><status>DONE</status></return><return><id>194263</id><source>CCMD</source><status>DONE</status></return><return><id>193740</id><source>CCMD</source><status>DONE</status></return></ns2:getLastUploadResponse></soap:Body></soap:Envelope>
--uuid:5c8a8a1d-a29c-43d0-baaa-cb3a8c189962--

Если вы посмотрите на верхнюю часть строки, она имеет значение ключа и другой персонал с сервера, который заставил класс SoapClient выдать исключение "похоже, у нас нет XML-документа". Несмотря на то, что XML-документ был ниже всех этих сотрудников.

--uuid:5c8a8a1d-a29c-43d0-baaa-cb3a8c189962
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml";
Content-Transfer-Encoding: binary
Content-ID: <root.message@cxf.apache.org>

Аналогично в нижней части строки (после XML) появляется тот же ключ

--uuid:5c8a8a1d-a29c-43d0-baaa-cb3a8c189962--

Таким образом, решение состояло в том, чтобы попытаться избавиться от части строки от начала до начала файла XML и от конца файла XML до конца строки. Я нашел очень хороший скрипт, который помог мне подойти к этому решению здесь MTOM php клиент. Тем не менее, мой ответ xml был немного другим, поэтому я немного изменил этот скрипт, и вот моя версия.

function upload_file_insert_via_soap_obj( $token, $csv_file )
{
    try
    {
        $wsdl_loc = 'https:XXX/apibatchmember/services/BatchMemberService?wsdl';

        $soap_Object = new MTOMSoapClient( $wsdl_loc, array( 'cache_wsdl' => WSDL_CACHE_NONE, 'trace' => true ) );

        $parameters['token'] = $token;
        $parameters['insertUpload']['fileName'] = "insertMemberTest.txt";
        $parameters['insertUpload']['fileEncoding'] = "UTF-8";
        $parameters['insertUpload']['separator'] = ",";
        $parameters['insertUpload']['skipFirstLine'] = "false";
        $parameters['insertUpload']['autoMapping'] = "true"; 

        $parameters['file'] = file_get_contents( "insertMemberTest.txt" );

        $results = $soap_Object->uploadFileInsert( $parameters );

        $upload_id = $results->return;

        echo "<br/>upload_id: ".$upload_id;  
        return $upload_id;  
    }
    catch ( Exception $exception )
    {
        echo "EX REQUEST: " . $soap_Object->__getLastRequest() . "<br/>";
        echo "EX RESPONSE: " . $soap_Object->__getLastResponse() . "<br/>";
        echo "<br/>Response var dump: "; var_dump( $soap_Object->__getLastResponse() ); echo "<br/>";

        echo '<br/><br/> Exception: '.$exception->getMessage()."<br/>";
        var_dump( $exception );
    }
}


/**
* This client extends the ususal SoapClient to handle mtom encoding. Due
* to mtom encoding soap body has test apart from valid xml. This extension
* remove the text and just keeps the response xml.
*/

class MTOMSoapClient extends SoapClient 
{

    public function __doRequest( $request, $location, $action, $version, $one_way = 0 ) 
    {
        $response = parent::__doRequest( $request, $location, $action, $version, $one_way );
        //if resposnse content type is mtom strip away everything but the xml.
        if ( strpos( $response, "Content-Type: application/xop+xml" ) !== false ) 
        {
            //not using stristr function twice because not supported in php 5.2 as shown below
            //$response = stristr(stristr($response, "<s:"), "</s:Envelope>", true) . "</s:Envelope>";
            $tempstr = stristr( $response, "<soap:" );
            $response = substr( $tempstr, 0, strpos( $tempstr, "</soap:Envelope>" ) ) . "</soap:Envelope>";
        }
        //log_message($response);
        return $response;
    }

}

Я не уверен, что это подходящее место для этого, но мне было трудно заставить мою Службу Windows подключиться к WSDL (используя автоматически сгенерированную веб-ссылку).

Я получил ту же ошибку, что и оригинальный постер здесь. Так как я не использую WCF, app.config не будет работать для меня, и мой сервис не запустится. Я нашел пост в MSDN, где AjayChigurupati заявляет, что нужно изменить

public partial class WsdlService : System.Web.Services.Protocols.SoapHttpClientProtocol {...}

к

public partial class WsdlService : Microsoft.Web.Services3.WebServicesClientProtocol {...}

(Обязательно добавьте Microsoft.Web.Services3 ссылка на ваш проект)

Теперь у нас есть доступ к логическому свойству RequireMtom и вы можете окружить свою вызывающую функцию следующим образом:

    public DownloadResponse downloadDataFile([System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] DownloadRequest Request) {
        RequireMtom = true; // ADDED
        object[] results = this.Invoke("downloadDataFile", new object[] {
                    Request});
        RequireMtom = false; // ADDED
        return ((DownloadResponse)(results[0]));
    }

Надеюсь, это поможет кому-то еще с той же проблемой в будущем.

Я только что получил эту проблему, потому что < configSections> не был первым элементом в < configuration>.

Другие вопросы по тегам