Ошибка при использовании webservice, тип контента "application/xop + xml" не соответствует ожидаемому типу "text/xml"
У меня возникла странная проблема при использовании веб-сервиса для продукта, купленного моей компанией. Продукт называется Commaign 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="<[email protected]>"; 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: <[email protected]>
<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--
--.
Как вы можете видеть, конверт soap ответа выглядит действительным (это правильный ответ и успешный вызов), но у клиента возникает проблема с типом контента и генерируется исключение.
Ошибка использования служебной ссылки (клиент WCF)
Когда я использую службу как ссылку на службу, я получаю ProtocolException
для любого вызова, который я делаю, со следующим сообщением:
The content type multipart/related; type="application/xop+xml"; boundary="uuid:af66440a-012e-4444-8814-895c843de5ec"; start="<[email protected]>"; 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: <[email protected]>
<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, но ничего, что я нашел, помог мне до сих пор.
Ответы
Ответ 1
Для тех, кто страдает от одной и той же проблемы; Я нашел решение для использования веб-службы как Service Reference (WCF). Для свойства BasicHttpBinding.MessageEncoding требуется значение "Mtom".
Здесь приведен фрагмент требуемой конфигурации:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding messageEncoding="Mtom">
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
Изменить: если у вас такая же проблема с пользовательской привязкой, обратитесь к от @robmzd.
Я до сих пор не нашел решения для того, чтобы использовать его как веб-ссылку старого стиля.
Ответ 2
После того, как я боролся с этим в течение нескольких дней, я нашел замечательное решение этой проблемы:
- Активируйте Редактор конфигурации, выбрав Tools- > Редактор конфигурации службы WCF из главного меню в VS2010;
- Закройте его еще раз;
- Щелкните правой кнопкой мыши файл App.Config, чтобы найти новый пункт меню "Редактировать конфигурацию WCF";
- Нажмите на ссылку;
- Измените MessageEncoding на Mtom;
- Сохранить.
Надеюсь, это поможет кому-то.
Ответ 3
У меня точно такая же проблема с той же функцией и с той же компанией, и я провожу пару часов в Google, пытаясь найти правильный ответ. После стольких испытаний я наконец получил это. Вот что я сделал: Следующая строка была ответом, который работает от Email Vision, где я возвращаюсь (моей главной целью была массовая загрузка, но я просто поменю на getLastUpload для простоты и тестирования).
string (2180) "
--uuid:5c8a8a1d-a29c-43d0-baaa-cb3a8c189962
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml";
Content-Transfer-Encoding: binary
Content-ID: <[email protected]>
<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: <[email protected]f.apache.org>
Аналогично внизу строки (после xml) появляется тот же самый ключ
--uuid:5c8a8a1d-a29c-43d0-baaa-cb3a8c189962--
Таким образом, решение заключалось в том, чтобы попытаться избавиться от части строки от начала до начала файла xml и от конца XML файла до конца строки. Я нашел очень хороший script, который помог мне подойти к этому решению здесь MTOM php client. Тем не менее, мой ответ xml был немного другим, поэтому я немного изменил этот script и вот моя версия.
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;
}
}
Ответ 4
Если вы являетесь владельцем службы WCF, и вы используете эту услугу клиентом WCF. Не забудьте установить свойство MessageEncoding
в хосте следующим образом:
BasicHttpBinding binding = new BasicHttpBinding();
binding.MessageEncoding = WSMessageEncoding.Mtom;
Я столкнулся с этой проблемой. Мой клиент продолжал бросать это исключение при запуске, и я не мог понять, почему, пока не понял, что забыл установить свойство bind MessageEncoding
в хост-приложении.
Ответ 5
У меня была такая же проблема, но с <customBinding>
. Чтобы исправить это, вы можете настроить кодировку сообщений Mtom с помощью отдельной конфигурации <mtomMessageEncoding>
node под привязкой.
<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>
Ответ 6
У меня возникла эта проблема, потому что < configSections > не был первым элементом в < конфигурации.
Ответ 7
Я не уверен, что это подходящее место для этого, но мне было трудно заставить мою службу 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]));
}
Надеюсь, это поможет кому-то другому с той же проблемой в будущем.