可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm having a weird issue when consuming a webservice for a product that my company has bought. The product is called Campaign Commander and it's made by a company called Email Vision. We're trying to use the "Data Mass Update SOAP API".
Whenever I try to call any of the methods on the webservice, the call actually succeeds but the client fails when processing the response and I get an exception.
The details of the errors are below, thanks for any help you guys can offer.
Error using Web Reference (old style webservice client)
When consume the service as a Web Reference I get an InvalidOperationException
for any call that I make, with the following message:
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--
--.
As you can see, the response soap envelope looks valid (this is a valid response and the call succeeded), but the client seems to have a problem with the content type and generates an exception.
Error using Service Reference (WCF client)
When I consume the service as a Service Reference I get a ProtocolException
for any call that I make, with the following message:
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--'.
Just like with the previous example; we've got a valid soap response and the call was successful, but the client seems to have a problem with the content type and has generated an exception.
Are there any options I can set so the client doesn't have a problem with the response type? I've done some Google searches, but nothing that I've found has helped me so far.
回答1:
For anyone suffering from the same problem; I've found a solution for consuming the web service as a Service Reference (WCF). The BasicHttpBinding.MessageEncoding property needs setting to "Mtom".
Here's a snippet of the required config setting:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding messageEncoding="Mtom">
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
Edit: If you are having the same issue with a custom binding please refer to the answer from @robmzd.
I still haven't found a solution for consuming it as an old style Web Reference yet.
回答2:
After having struggled with this for a few days, I found a remarkably simple solution for this problem:
- Activate the Configuration Editor by selecting Tools->WCF Service Configuration Editor from the main menu in VS2010;
- Close it again;
- Right-click on the App.Config file to find a new menu item "Edit WCF Configuration";
- Click on the binding;
- Change the MessageEncoding to Mtom;
- Save.
I hope this will help someone.
回答3:
I got exactly the same problem with the same function and the same company and I spend a couple of hours on Google trying to find the right answer. After so many trials I finally got it. Here is what I did: The following string was the response that functions from Email Vision where returning me (My main purpose was Mass Upload but I swap to getLastUpload for simplicity and testing).
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: <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--
If you look at the top of the string it has a key value and other staff from the server which made the SoapClient class to throw an exception "looks like we got no XML document". Eventhough the xml document was below all this staff.
--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>
Similarly at the bottom of the string (after the xml) the same key appears
--uuid:5c8a8a1d-a29c-43d0-baaa-cb3a8c189962--
So the solution was to try to get rid of the part of the string from the beginning to the start of the xml file and from the end of the xml file to the end of the string. I found a very good script that helped me to approach this solution here MTOM php client. However, my response xml was a bit different so I just modified that script a little bit and here is my version.
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:
If you're self-hosting a WCF service and you're consuming the service with a WCF client. You must remember to set the MessageEncoding
property in the host like this:
BasicHttpBinding binding = new BasicHttpBinding();
binding.MessageEncoding = WSMessageEncoding.Mtom;
I ran into this problem as well. My client kept throwing this Exception on start up and I couldn't figure out why until I realized that I forgot to set my bindings MessageEncoding
property in the host application.
回答5:
I had the same issue but with <customBinding>
. To fix it you can configure Mtom Message Encoding using a separate <mtomMessageEncoding>
configuration node under the binding.
<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:
I just got this problem because <configSections> was not the first element in <configuration>.
回答7:
I'm not sure if this is any appropriate place to put this, but I was having a hard time getting my Windows Service to connect to a WSDL (using an auto generated web reference).
I was getting the same error as the original poster here. Since I'm not using WCF the app.config would not work for me and caused my service not to start. I did find a post on MSDN where AjayChigurupati states to change
public partial class WsdlService : System.Web.Services.Protocols.SoapHttpClientProtocol {...}
To
public partial class WsdlService : Microsoft.Web.Services3.WebServicesClientProtocol {...}
(Make sure to add the Microsoft.Web.Services3
reference to your project)
Now we have access to the boolean property RequireMtom
and you can surround your calling function like so:
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]));
}
Hopefully this helps someone else with the same problem in the future.