Requêtes SOAP en .NET

Nous essayons d’utiliser des requêtes SOAP pour interagir avec une API de réservation à l’aide de Visual Studio C #.

Nous avons interfacé avec un service Web d’une autre API sans problème, mais celui-ci s’avère problématique.

Nous l’avons ajouté en tant que référence de service et Visual Studio a généré toutes les classes et entrées web.config afin que tout semble bien se passer.

Cependant, lorsque nous essayons de faire une simple demande au service SOAP client, nous obtenons l’erreur suivante:

Namespace = ‘com.hrs.soap.hrs’ n’est pas pris en charge avec SOAP rpc \ literal. L’élément wrapper doit être non qualifié.

Le code est:

PingRequest pingrequest = new PingRequest(); SoapServiceClient service = new SoapServiceClient(); service.ping(pingrequest); 

Ce qui a été ajouté dans le fichier Web.config:

                 

Selon la documentation, la demande devrait ressembler à ceci:

          

Trace complète de la stack ci-dessous:

 [InvalidOperationException: Namespace='com.hrs.soap.hrs' is not supported with rpc\literal SOAP. The wrapper element has to be unqualified.] System.Xml.Serialization.XmlReflectionImporter.CheckTopLevelAtsortingbutes(XmlAtsortingbutes a, Ssortingng accessorName) +842469 System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAtsortingbutes a, Ssortingng ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +4072651 System.Xml.Serialization.XmlReflectionImporter.ImportMemberMapping(XmlReflectionMember xmlReflectionMember, Ssortingng ns, XmlReflectionMember[] xmlReflectionMembers, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +699 System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(XmlReflectionMember[] xmlReflectionMembers, Ssortingng ns, Boolean hasWrapperElement, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +298 [InvalidOperationException: There was an error reflecting 'HRSException'.] System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(XmlReflectionMember[] xmlReflectionMembers, Ssortingng ns, Boolean hasWrapperElement, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +1051 System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(Ssortingng elementName, Ssortingng ns, XmlReflectionMember[] members, Boolean hasWrapperElement, Boolean rpc, Boolean openModel, XmlMappingAccess access) +137 System.ServiceModel.Description.XmlSerializerImporter.ImportMembersMapping(XmlName elementName, Ssortingng ns, XmlReflectionMember[] members, Boolean hasWrapperElement, Boolean rpc, Boolean isEncoded, Ssortingng mappingKey) +237 System.ServiceModel.Description.OperationReflector.ImportMembersMapping(Ssortingng elementName, Ssortingng ns, XmlReflectionMember[] members, Boolean hasWrapperElement, Boolean rpc, Ssortingng mappingKey) +134 System.ServiceModel.Description.OperationReflector.ImportFaultElement(FaultDescription fault, XmlQualifiedName& elementName) +458 System.ServiceModel.Description.OperationReflector.GenerateXmlSerializerFaultContractInfos() +153 System.ServiceModel.Description.OperationReflector.EnsureMessageInfos() +929 System.ServiceModel.Description.Reflector.EnsureMessageInfos() +98 System.ServiceModel.Description.XmlSerializerOperationBehavior.CreateFormatter() +32 System.ServiceModel.Description.XmlSerializerOperationBehavior.System.ServiceModel.Description.IOperationBehavior.ApplyClientBehavior(OperationDescription description, ClientOperation proxy) +42 System.ServiceModel.Description.DispatcherBuilder.BindOperations(ContractDescription contract, ClientRuntime proxy, DispatchRuntime dispatch) +94 System.ServiceModel.Description.DispatcherBuilder.ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime clientRuntime) +247 System.ServiceModel.Description.DispatcherBuilder.BuildProxyBehavior(ServiceEndpoint serviceEndpoint, BindingParameterCollection& parameters) +342 System.ServiceModel.Channels.ServiceChannelFactory.BuildChannelFactory(ServiceEndpoint serviceEndpoint, Boolean useActiveAutoClose) +85 System.ServiceModel.ChannelFactory.CreateFactory() +43 System.ServiceModel.ChannelFactory.OnOpening() +23 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +274 System.ServiceModel.ChannelFactory.EnsureOpened() +107 System.ServiceModel.ChannelFactory`1.CreateChannel(EndpointAddress address, Uri via) +134 System.ServiceModel.ChannelFactory`1.CreateChannel() +29 System.ServiceModel.ClientBase`1.CreateChannel() +91 System.ServiceModel.ClientBase`1.CreateChannelInternal() +26 System.ServiceModel.ClientBase`1.get_Channel() +261 BLL.HRSService.HRSSoapServiceClient.ping(HRSPingRequest pingRequest) in C:\Code\-------\BLL\Service References\HRSService\Reference.cs:15850 -------.Test.Ping() in C:\Code\-------\Test.aspx.cs:48 -------.Test.Page_Load(Object sender, EventArgs e) in C:\Code\-------\Test.aspx.cs:24 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35 System.Web.UI.Control.OnLoad(EventArgs e) +91 System.Web.UI.Control.LoadRecursive() +74 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207 

Nous avons installé Fiddler et nous ne pouvons voir aucune requête XML en cours, probablement parce qu’elle lève une exception avant que quoi que ce soit ne soit envoyé.

Que devons-nous changer exactement dans notre configuration pour que cela fonctionne?

METTRE À JOUR

WSDL: disponible [ici] [1]

METTRE À JOUR

À la suite des excellents conseils de davidfmatheson, j’ai copié le WSDL localement et apporté les modifications suggérées. Je reçois toujours la même erreur bien que possiblement dans un endroit différent:

 [System.ComponentModel.EditorBrowsableAtsortingbute(System.ComponentModel.EditorBrowsableState.Advanced)] BLL.HRSService.pingResponse BLL.HRSService.HRSSoapService.ping(BLL.HRSService.pingRequest request) { return base.Channel.ping(request); } public BLL.HRSService.HRSPingResponse ping(BLL.HRSService.HRSPingRequestWrapper ping1) { BLL.HRSService.pingRequest inValue = new BLL.HRSService.pingRequest(); inValue.ping = ping1; BLL.HRSService.pingResponse retVal = ((BLL.HRSService.HRSSoapService)(this)).ping(inValue); return retVal.pingResponse1; } 

La ligne qui échoue est le retour base.Channel.ping (demande); avec l’erreur Namespace = ‘com.hrs.soap.hrs’ n’est pas pris en charge avec SOAP rpc \ literal. L’élément wrapper doit être non qualifié.

J’ai aussi essayé de définir explicitement le SOAPBinding:

 Exception Details: System.InvalidOperationException: Namespace='com.hrs.soap.hrs' is not supported with rpc\literal SOAP. The wrapper element has to be unqualified. Source Error: Line 15917: [System.Web.Services.Protocols.SoapDocumentMethod(Use = System.Web.Services.Description.SoapBindingUse.Literal)] Line 15918: BLL.HRSService.pingResponse BLL.HRSService.HRSSoapService.ping(BLL.HRSService.pingRequest request) { Line 15919: return base.Channel.ping(request); Line 15920: } Line 15921: 

OK maintenant, j’ai modifié le style de liaison SOAP afin de documenter dans mon WSDL local et de recréer les classes. J’ai une erreur différente:

 Unable to generate a temporary class (result=1). error CS0030: Cannot convert type 'BLL.HRSService.HRSHotelTaxDetail[]' to 'BLL.HRSService.HRSHotelTaxDetail' error CS0030: Cannot convert type 'BLL.HRSService.HRSHotelAmenityCriterion[]' to 'BLL.HRSService.HRSHotelAmenityCriterion' error CS0029: Cannot implicitly convert type 'BLL.HRSService.HRSHotelTaxDetail' to 'BLL.HRSService.HRSHotelTaxDetail[]' error CS0029: Cannot implicitly convert type 'BLL.HRSService.HRSHotelAmenityCriterion' to 'BLL.HRSService.HRSHotelAmenityCriterion[]' 

Trace de la stack:

 [InvalidOperationException: Unable to generate a temporary class (result=1). error CS0030: Cannot convert type 'BLL.HRSService.HRSHotelTaxDetail[]' to 'BLL.HRSService.HRSHotelTaxDetail' error CS0030: Cannot convert type 'BLL.HRSService.HRSHotelAmenityCriterion[]' to 'BLL.HRSService.HRSHotelAmenityCriterion' error CS0029: Cannot implicitly convert type 'BLL.HRSService.HRSHotelTaxDetail' to 'BLL.HRSService.HRSHotelTaxDetail[]' error CS0029: Cannot implicitly convert type 'BLL.HRSService.HRSHotelAmenityCriterion' to 'BLL.HRSService.HRSHotelAmenityCriterion[]' ] System.Xml.Serialization.Comstackr.Comstack(Assembly parent, Ssortingng ns, XmlSerializerComstackrParameters xmlParameters, Evidence evidence) +1024 System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, Ssortingng defaultNamespace, Evidence evidence, XmlSerializerComstackrParameters parameters, Assembly assembly, Hashtable assemblies) +1997 System.Xml.Serialization.XmlSerializer.GetSerializersFromCache(XmlMapping[] mappings, Type type) +772 System.Xml.Serialization.XmlSerializer.FromMappings(XmlMapping[] mappings, Type type) +4066268 System.ServiceModel.Description.SerializerGenerationContext.GenerateSerializers() +185 System.ServiceModel.Description.SerializerGenerationContext.GetSerializer(Int32 handle) +102 System.ServiceModel.Description.MessageInfo.get_BodySerializer() +17 System.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, Ssortingng action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest) +112 [CommunicationException: There was an error in serializing body of message pingRequest: 'Unable to generate a temporary class (result=1). error CS0030: Cannot convert type 'BLL.HRSService.HRSHotelTaxDetail[]' to 'BLL.HRSService.HRSHotelTaxDetail' error CS0030: Cannot convert type 'BLL.HRSService.HRSHotelAmenityCriterion[]' to 'BLL.HRSService.HRSHotelAmenityCriterion' error CS0029: Cannot implicitly convert type 'BLL.HRSService.HRSHotelTaxDetail' to 'BLL.HRSService.HRSHotelTaxDetail[]' error CS0029: Cannot implicitly convert type 'BLL.HRSService.HRSHotelAmenityCriterion' to 'BLL.HRSService.HRSHotelAmenityCriterion[]' '. Please see InnerException for more details.] System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +9440287 System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +345 BLL.HRSService.HRSSoapService.ping(pingRequest request) +0 BLL.HRSService.HRSSoapServiceClient.BLL.HRSService.HRSSoapService.ping(pingRequest request) in C:\Code\...\BLL\Service References\HRSService\Reference.cs:17311 BLL.HRSService.HRSSoapServiceClient.ping(HRSPingRequestWrapper ping1) in C:\Code\...\BLL\Service References\HRSService\Reference.cs:17317 BLL.HRS_Integration.Ping() in C:\Code\...\BLL\General\HRSIntegration.cs:55 VenueOptions.Test.Page_Load(Object sender, EventArgs e) in C:\Code\...\Test.aspx.cs:24 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35 System.Web.UI.Control.OnLoad(EventArgs e) +91 System.Web.UI.Control.LoadRecursive() +74 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207 

Demande enfin faite!

Le violoniste montre ce qui suit pour PING:

 .........Hello HRS 

Vous essayez de consumr un service littéral RPC à partir de .NET. Vous devrez peut-être convertir le service en doc-literal. Voir le blog MSDN .

EDIT: réponse plus complète

Le but est de pouvoir utiliser doc-literal, tout en envoyant le même message. Concentrons-nous sur l’opération de ping . Actuellement, votre type de fichier WSDL est défini comme suit:

          

Et votre message défini comme:

    

Et votre reliure définie comme:

                

Donc, localement, nous modifions le “rpc” en “document”, puis corrigeons le WSDL en document / literal:

                ...    

Générez maintenant ce WSDL et voyez s’il envoie une requête ping. Si vous ne corrigez pas la structure de la réponse, il se peut que vous ne compreniez pas ce qui est renvoyé, mais vous devriez au moins voir une demande envoyée par câble. Vous pouvez utiliser SoapUI pour charger les deux WSDL et voir quel type de demande est généré. L’objective est d’envoyer la même demande, en utilisant simplement document / literal au lieu de rpc / literal.