I have a problem in my C# ASP.NET MVC web app where we are trying to add multiple references to different versions of the Magento API.
Basically my app needs to be able to connect to different Magento ecommerce stores. Some of these stores could be version 1.4, some could be 1.5 and so on. To handle this situation I have added multiple web references, one for each of the versions:
<applicationSettings>
<WebApp.Properties.Settings>
<setting name="WebApp_MagentoWebReference_MagentoService"
serializeAs="String">
<value>http://example.com/magento1411/index.php/api/v2_soap/index/</value>
</setting>
<setting name="WebApp_Magento1510WebReference_MagentoService"
serializeAs="String">
<value>http://example.com/magento1510/index.php/api/v2_soap/index/</value>
</setting>
</WebApp.Properties.Settings>
</applicationSettings>
And then in the code I make sure to create an instance using the right web reference that matches the version I am targeting:
string url = "http://example.com/magento1411/index.php/api/v2_soap/";
_magentoService = new MagentoWebReference.MagentoService();
_magentoService.Url = url;
string apiUser = "user";
string apiKey = "key";
sessionId = _magentoService.login(apiUser, apiKey);
var magentoProductList = _magentoService.catalogProductList(sessionId, null, null);
You can see that I am deliberately creating the version 1.4 web reference when requesting the product list from a version 1.4 shop. However when this code runs it fails with this error:
Cannot assign object of type WebApp.Magento1510WebReferen开发者_Python百科ce.salesOrderInvoiceEntity[]
to an object of type WebApp.MagentoWebReference.salesOrderInvoiceEntity[].
For some reason the return value is of type Magento1510WebReference.salesOrderInvoiceEntity
.
Is there any known problem adding multiple web references like this? Is Visual Studio or IIS getting confused between the two references?
This is the full stack trace:
System.Exception: There was a problem recieving a list of invoices from mageto store: http://example.com ---> System.InvalidOperationException: There is an error in XML document (2, 485). ---> System.InvalidCastException: Cannot assign object of type WebApp.Magento1510WebReference.salesOrderInvoiceEntity[] to an object of type WebApp.MagentoWebReference.salesOrderInvoiceEntity[].
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read351_salesOrderInvoiceListResponse()
at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer469.Deserialize(XmlSerializationReader reader)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at WebApp.MagentoWebReference.MagentoService.salesOrderInvoiceList(String sessionId, filters filters) in C:\src\WebApp.2010\WebApp.UI\Web References\MagentoWebReference\Reference.cs:line 3073
at WebApp.Controllers.Magento.MagentoController.GetLatestInvoices() in C:\src\WebApp.2010\WebApp.UI\Controllers\Magento\MagentoController.cs:line 217
--- End of inner exception stack trace ---
I can see that when the response comes back from the Magento API that the XmlSerializer.Deserialize is getting confused and thinks that the XML comes from the Magento 1.5 reference, not the Magento 1.4 reference. The question is why does it do this, and how can it be fixed?
EDIT:
As I suspected the soap envelope of the response from the Magento API is actually the same for both versions:
1.4.1 soap = <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:Magento" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:loginResponse><loginReturn xsi:type="xsd:string">6325f7753ea72ba70e0a04254d58abe5</loginReturn></ns1:loginResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
1.5.1 soap = <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:Magento" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:loginResponse><loginReturn xsi:type="xsd:string">90ebce956623bb7e1637165306de40d0</loginReturn></ns1:loginResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
Which means that when the response is received, the Xml Deserializer cannot work out which of the web references to use because both of them match the response signature. And it ends up using the Magento1510 reference to deserialize, when it should have been the Magento1411 reference. Is there anything I can do about this? (I have started trying out the answer that suggests to split the references into separate projects)
If the WCF service is versioned in a good way you should be able to talk with the 1.4 version even if you use the 1.5 assemblies. Have you tried this?
If that doesn't work I think you need to seperate the proxy for each version into a new project. This way you can make sure the proxy only knows about the current version and you can avoid the namespace conflicts.
精彩评论