2012-08-03 15 views
6

Staramy się używać żądań SOAP do interakcji z API rezerwacji za pomocą Visual Studio C#.Żądania SOAP w .NET

Nawiązaliśmy połączenie z usługą sieci Web innego interfejsu API bez problemu, ale ten problem jest problematyczny.

Dodaliśmy go jako odniesienie do usługi, a Visual Studio wygenerowało wszystkie klasy dla niego i wpisy w pliku web.config, aby wszystko było dobrze.

Jednak gdy staramy się zrobić prosty wniosek do Służby SOAP klienta otrzymujemy następujący błąd:

Namespace='com.hrs.soap.hrs' is not supported with rpc\literal SOAP. The wrapper element has to be unqualified.

Kod jest:

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

To, co zostało dodane w sieci. plik konfiguracyjny:

<system.serviceModel> 
    <bindings> 
     <basicHttpBinding> 
     <binding name="HRSSoapServiceBinding" closeTimeout="00:01:00" 
      openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" 
      allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" 
      maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" 
      messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" 
      useDefaultWebProxy="true"> 
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
       maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
      <security mode="None"> 
      <transport clientCredentialType="None" proxyCredentialType="None" 
       realm="" /> 
      <message clientCredentialType="UserName" algorithmSuite="Default" /> 
      </security> 
     </binding> 
     </basicHttpBinding> 
    </bindings> 
    <client> 
     <endpoint address="..." 
      binding="basicHttpBinding" bindingConfiguration="HRSSoapServiceBinding" 
      contract="HRSService.HRSSoapService" name="HRSSoapServicePort" /> 
    </client> 
    </system.serviceModel> 

Zgodnie z dokumentacją wniosek powinien wyglądać jak llowing:

<complexType name="PingRequest"> 
    <complexContent> 
     <extension base="tns:Request"> 
      <sequence> 
       <element name="echoData" type="xsd:string"/> 
      </sequence> 
     </extension> 
    </complexContent> 
</complexType> 

Pełna Śledzenie stosu poniżej:

[InvalidOperationException: Namespace='com.hrs.soap.hrs' is not supported with rpc\literal SOAP. The wrapper element has to be unqualified.] 
    System.Xml.Serialization.XmlReflectionImporter.CheckTopLevelAttributes(XmlAttributes a, String accessorName) +842469 
    System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +4072651 
    System.Xml.Serialization.XmlReflectionImporter.ImportMemberMapping(XmlReflectionMember xmlReflectionMember, String ns, XmlReflectionMember[] xmlReflectionMembers, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +699 
    System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(XmlReflectionMember[] xmlReflectionMembers, String ns, Boolean hasWrapperElement, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +298 

[InvalidOperationException: There was an error reflecting 'HRSException'.] 
    System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(XmlReflectionMember[] xmlReflectionMembers, String ns, Boolean hasWrapperElement, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +1051 
    System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(String elementName, String ns, XmlReflectionMember[] members, Boolean hasWrapperElement, Boolean rpc, Boolean openModel, XmlMappingAccess access) +137 
    System.ServiceModel.Description.XmlSerializerImporter.ImportMembersMapping(XmlName elementName, String ns, XmlReflectionMember[] members, Boolean hasWrapperElement, Boolean rpc, Boolean isEncoded, String mappingKey) +237 
    System.ServiceModel.Description.OperationReflector.ImportMembersMapping(String elementName, String ns, XmlReflectionMember[] members, Boolean hasWrapperElement, Boolean rpc, String 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 

Zainstalowaliśmy Skrzypek i nie ma żądania XML przeżywa, że ​​możemy zobaczyć, przypuszczalnie dlatego, że zgłasza wyjątek, zanim cokolwiek zostanie wysłana.

Co dokładnie musimy zmienić w naszej konfiguracji, aby to działało?

UPDATE

WSDL: Dostępne [tutaj] [1]

UPDATE

Po davidfmatheson za doskonałą poradę mam skopiowany WSDL lokalnie i wykonane poprawki jak sugeruje . Ja wciąż otrzymuję ten sam błąd, chociaż być może w innym miejscu:

[System.ComponentModel.EditorBrowsableAttribute(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; 
     } 

Linia, która nie jest base.Channel.ping powrotny (request); z błędem Namespace = "com.hrs.soap.hrs" nie jest obsługiwane przez SOAP \ rpc \ literal. Element owijający musi być nieklasyfikowany.

Próbowałem też jawnie ustawić 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 teraz mam zmieniła SOAP Binding styl dokument w moim lokalnym WSDL i odtworzone klas i mam inny błąd:

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[]' 

StackTrace:

[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.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence) +1024 
    System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters 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, String 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 

Wniosek ostatecznie złożony!

Skrzypek pokazuje następujące informacje dotyczące Ping:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><ping xmlns="com.hrs.soap.hrs"><pingRequest xmlns=""><credentials><clientType>...</clientType><clientKey>...</clientKey><clientPassword>...</clientPassword><customerKey xsi:nil="true"/></credentials><myHRSCredentials xsi:nil="true"/><echoData>Hello HRS</echoData></pingRequest></ping></s:Body></s:Envelope> 
+0

Sprawdź ślad stosu i zobacz, gdzie pęknięty jest twój kod. Czy to w fazie budowania żądania czy w fazie dese serializacji odpowiedzi? – linkerro

+0

Nie jestem pewien, szczerze mówiąc, Stack Trace dodano – cusimar9

+0

Z ciekawości, czy jest wsdl.exe zdolny do generowania działającego proxy? –

Odpowiedz

6

Próbujesz konsumować usługę RPC-dosłowne .NET, więc być może trzeba będzie przekształcić usługę doc-dosłownym. Zobacz MSDN Blog.

EDIT: Więcej kompletna odpowiedź

Celem jest, aby móc korzystać z doc-dosłowny, ale nadal wysyłać tę samą wiadomość. Skupmy się na operacji ping. Teraz Twój WSDL ma typ zdefiniowany jako:

<complexType name="HRSPingRequest"> 
    <complexContent> 
     <extension base="tns:HRSRequest"> 
      <sequence> 
       <element name="echoData" type="xsd:string"/> 
      </sequence> 
     </extension> 
    </complexContent> 
</complexType> 

And wiadomości zdefiniowana jako:

<message name="HRSSoapService_pingRequest"> 
    <part name="pingRequest" type="tns:HRSPingRequest"/> 
</message> 

i twoi wiązanie zdefiniowano jako:

<binding name="HRSSoapServiceBinding" type="tns:HRSSoapService"> 
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> 
    <operation name="ping"> 
     <soap:operation soapAction=""/> 
     <input> 
      <soap:body namespace="com.hrs.soap.hrs" use="literal"/> 
     </input> 
     <output> 
      <soap:body namespace="com.hrs.soap.hrs" use="literal"/> 
     </output> 
     <fault name="HRSException"> 
      <soap:fault name="HRSException" use="literal"/> 
     </fault> 
    </operation> 
</binding> 

Więc lokalnie możemy zmienić „RPC "aby" udokumentować ", a następnie naprawić plik WSDL do rzeczywistego dokumentu/literału:

<element name="ping" type="tns:HRSPingRequestWrapper" /> 
<complexType name="HRSPingRequestWrapper"> 
    <sequence> 
     <element name="pingRequest" type="tns:HRSPingRequest" /> 
    </sequence> 
</complexType> 
<complexType name="HRSPingRequest"> 
    <complexContent> 
     <extension base="tns:HRSRequest"> 
      <sequence> 
       <element name="echoData" type="xsd:string"/> 
      </sequence> 
     </extension> 
    </complexContent> 
</complexType> 

... 

<message name="HRSSoapService_pingRequest"> 
    <part name="pingRequest" element="tns:ping"/> 
</message> 

Teraz wygeneruj ten plik WSDL i sprawdź, czy wysyła żądanie ping. Jeśli nie naprawisz struktury odpowiedzi, może nie rozumieć, co powróci, ale powinieneś przynajmniej zobaczyć żądanie wysłane przez przewód. Możesz użyć SoapUI do załadowania obu WSDL i zobacz, jaki rodzaj zgłoszeń jest generowany. Celem jest wysłanie tego samego żądania, używając tylko dokumentu/literału zamiast rpc/literału.

+0

Dzięki za link, będziemy mieli dobry przegląd. Nie, nie mamy kontroli nad producentem usług internetowych. Wszystko wydaje się bardziej skomplikowane, niż powinno być. – cusimar9

+0

Nie możemy przekonwertować usługi na doc-literal, ponieważ nie mamy kontroli nad samą usługą. Próbowaliśmy dodać [SoapRpcService (Use = SoapBindingUse.Literal)] do wszystkich generowanych automatycznie klas, ale otrzymujemy ten sam błąd. – cusimar9

+1

Wydaje mi się, że wpis w blogu dotyczy pobierania WSDL i schematu z usługi, zapisywania go lokalnie, modyfikowania w opisany sposób, generowania skrótów tego zmodyfikowanego lokalnego pliku WSDL, a następnie wskazywania klienta pod pierwotnym adresem punktu końcowego. Jest to stary wpis na blogu i nigdy tego nie próbowałem, ale myślę, że właśnie to sugerują. – davidfmatheson

Powiązane problemy