wcf icon indicating copy to clipboard operation
wcf copied to clipboard

Old SOAP service (web reference) - throwing 'Message {nameOfFunction} must not have headers to be used in RPC encoded style.'

Open hurrk opened this issue 6 years ago • 34 comments
trafficstars

This might not be the right place for this - it's not necessarily an error in dotnet/wcf. But I'm hoping you guys can either answer or point me to the right place.

I'm consuming a SOAP service that uses the old .NET Framework Web Services 2.0 (I believe, there is no .svc, but there is a WSDL).

I can consume this service in .NET Framework by going to 'Add service reference -> Advanced -> Add web reference". Works no problem.

In .NET Core, when I add it as a Connected Service, firstly the code is somewhat different. But I also get an error when I call any endpoint, that goes as follows:

'Message {nameOfFunction} must not have headers to be used in RPC encoded style.'

And well, yes, it did generate the code so that the functions are marked with RPC and encoded.

The error happens in System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.OperationReflector.LoadHeadersMapping(MessageDescription message, String mappingKey) when checking that MessageDescription message.Headers.Count > 0 (and IsEncoded is true). Do you think it's worthwhile chasing this error down? Is it likely that this kind of API is just not supported in .NET Core?

hurrk avatar Jul 19 '19 16:07 hurrk

P.s. I can publish the wsdl if anyone's interested.

hurrk avatar Jul 19 '19 16:07 hurrk

@dasetser Tooling related, could you provide @hurrk some guidance or more info about the error he got?

StephenBonikowsky avatar Jul 22 '19 17:07 StephenBonikowsky

@hurrk Old services like this are something we make a best effort to support with the connected service, but we've seen people running into issues with them. We can try to help you track down what's causing it, but putting a fix into the tool for this would be lower priority.

@mconnew Do you have any ideas why we would be getting this error? I know we have problems with arrays with XmlSerializer and Soap encoding, but this seems like an issue before they even get to that point. I'm not sure what we might be generating incorrectly.

dasetser avatar Jul 23 '19 17:07 dasetser

@hurrk, on a .NET Framework application, can you try using "Add Service Reference" and see if you get the same error on .NET Framework? The problem is that your service contract has been generated with a MessageHeaderAttribute on one of the parameters and that's not supported when using RPC encoded style contracts.
Can you provide your WSDL?

mconnew avatar Jul 23 '19 19:07 mconnew

I have exact problem with https://aodws.attendanceondemand.com:8192/cc1.aew/wsdl/IAeXMLBridge Works with Web Reference and exact RPC message as above when I try in core

mottykohn avatar Aug 06 '19 21:08 mottykohn

@mottykohn, I had a quick look at your wsdl and it does specify use of message headers. I've included a snippet of your WSDL here to show an example of it. We have a check in WCF to make sure that if it's rpc encoded that we don't allow headers to be specified. I have no idea why that is. If we created an experimental build with that check disabled, could you try it out? It might be that it doesn't work correctly so the check is there to prevent debugging why the wrong output is generated every time someone tries it.

<binding name="IAeXMLBridgebinding" type="tns:IAeXMLBridge">
  <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
  <operation name="interfaceBuild">
    <soap:operation soapAction="urn:AeXMLBridgeIntf-IAeXMLBridge#interfaceBuild" style="rpc"/>
    <input>
      <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:AeXMLBridgeIntf-IAeXMLBridge"/>
      <soap:header use="encoded" message="tns:interfaceBuild0headerRequest" part="TSessionHeader" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:AeXMLBridgeIntf"/>
    </input>
    <output>
      <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:AeXMLBridgeIntf-IAeXMLBridge"/>
      <soap:header use="encoded" message="tns:interfaceBuild0headerResponse" part="TSessionHeader" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:AeXMLBridgeIntf"/>
    </output>
  </operation>
</binding>

mconnew avatar Aug 13 '19 02:08 mconnew

@mconnew I'll be happy to try it!

mottykohn avatar Aug 13 '19 14:08 mottykohn

@mottykohn, I took a closer look at the code and it's not quite clear exactly what the change should be. The reason is the existing code here where it throws an exception if RPC encoded is being used creates an XmlReflectionMember object for the header based on isRpc=false and isEncoded=false. The confusion for me is when using RPC literal, it still passes rpc=false. If I simply remove the the IsEncoded check, then does the value of IsRpc need to be passed through? Basically what I'm saying is that I suspect a first pass attempt at a fix will get it wrong so I'm going to need a little help from you.

Can you capture an example request using the Web Services client from 2.0 and provide the SOAP message. You can remove the entire SOAP body, put dummy values in place for any data. It's the xml elements that I need to be kept intact including any attributes. But any text data (stuff between a start xml <element> and an end xml </element>) can be removed if sensitive. That way when testing I can make sure it outputs the XML the correct way.

mconnew avatar Aug 13 '19 19:08 mconnew

@mconnew Thanks for working on this! Here are 2 calls. Nothing sensitive here. Let me know if you need more or a specific call.

c# code: cc1.ClientServerDateTime();

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:tns="http://tempuri.org/" 
    xmlns:types="http://tempuri.org/encodedTypes" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <q1:ClientServerDateTime xmlns:q1="urn:AeXMLBridgeIntf-IAeXMLBridge" />
    </soap:Body>
</soap:Envelope>


c# code: cc1.getEmployeesSearchListBasic("a*", true, 5);

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:tns="http://tempuri.org/" 
    xmlns:types="http://tempuri.org/encodedTypes" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
        <q1:getEmployeesSearchListBasic xmlns:q1="urn:AeXMLBridgeIntf-IAeXMLBridge">
            <WildCard xsi:type="xsd:string">a*</WildCard>
            <Phoenetic xsi:type="xsd:boolean">true</Phoenetic>
            <MaxRecords xsi:type="xsd:int">5</MaxRecords>
        </q1:getEmployeesSearchListBasic>
    </soap:Body>
</soap:Envelope>

mottykohn avatar Aug 13 '19 20:08 mottykohn

@mottykohn, neither of those has a header parameter being shown. I took a deeper look at your wsdl and there's interesting where it looks like the Web Services generated client is missing some things. In the wsdl, there's a portType defined with the name IAeXMLBridge starting on line 5669. This basically defines the message pattern and message parts (think method parameters) used for the operation. The getEmployeesSearchListBasic operation defined in this portType starts on line 6390 and looks like this:

    <operation name="getEmployeesSearchListBasic">
      <input message="tns:getEmployeesSearchListBasic180Request"/>
      <output message="tns:getEmployeesSearchListBasic180Response"/>
    </operation>

Here's how the input message is defined:

  <message name="getEmployeesSearchListBasic180Request">
    <part name="WildCard" type="xs:string"/>
    <part name="Phoenetic" type="xs:boolean"/>
    <part name="MaxRecords" type="xs:int"/>
  </message>

This basically says there are 3 parts to the request that will be sent to the service. There's a corresponding declared message for the output return.

In your wsdl you also have a binding which lists the operations again but giving some details of how the message is to be sent including things like specifying the encoding style (rpc vs literal) and what transport it's using (http in this case). This binding has the name IAeXMLBridgebinding and starts on line 6919. It specifies the type as tns:IAeXMLBridge which simply means all the operations defined in the portType IAeXMLBridge will exist on this binding. Here's the same operation with more implementation information as defined in the binding starting on line 8901:

    <operation name="getEmployeesSearchListBasic">
      <soap:operation soapAction="urn:AeXMLBridgeIntf-IAeXMLBridge#getEmployeesSearchListBasic" style="rpc"/>
      <input>
        <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:AeXMLBridgeIntf-IAeXMLBridge"/>
        <soap:header use="encoded" message="tns:getEmployeesSearchListBasic180headerRequest" part="TSessionHeader" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:AeXMLBridgeIntf"/>
      </input>
      <output>
        <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:AeXMLBridgeIntf-IAeXMLBridge"/>
        <soap:header use="encoded" message="tns:getEmployeesSearchListBasic180headerResponse" part="TSessionHeader" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:AeXMLBridgeIntf"/>
      </output>
    </operation>

The input body element doesn't include a parts attribute which means all the parts declared in the input message will be output in the soap body. What's interesting is that there's also a header defined in the input, but it declares it's using a different message type than the operation input message type. This getEmployeesSearchListBasic180headerRequest message is declared on line 4053 and looks like this:

  <message name="getEmployeesSearchListBasic180headerRequest">
    <part name="TSessionHeader" type="ns1:TSessionHeader"/>
  </message>

The type TSessionHeader is defined on line 1887 and looks like this:

      <xs:complexType name="TSessionHeader">
        <xs:sequence>
          <xs:element name="Account" type="xs:string"/>
          <xs:element name="Password" type="xs:string"/>
          <xs:element name="ClientCode" type="xs:string"/>
        </xs:sequence>
      </xs:complexType>

So without seeing the generated code, I'm guessing the generated code from WCF Connected Service tool included a class with the name TSessionHeader and the getEmployeesSearchListBasic generated method had an extra parameter to pass an object of this type in, and that parameter was attributed with [MessageHeaderAttribute]. Apparently your service is okay with not having this header added and it's optional and the Web Services client generated code without it.

So the TLDR for you is modify the wsdl to remove all <soap:header> elements from the binding and regenerate the client and I believe it should work. As the generated Web Services client didn't do anything with the headers defined in the wsdl, I think it's safe to say that this fix is likely to work for @hurrk too.

mconnew avatar Aug 14 '19 00:08 mconnew

@hurrk and @mottykohn let us know if this doesn't work for you.

StephenBonikowsky avatar Aug 14 '19 23:08 StephenBonikowsky

@mconnew @StephenBonikowsky I'll try sometime beginning next week and post. I have some deadlines to meet by the end of this week. Sorry, and thanks for helping!

mottykohn avatar Aug 15 '19 04:08 mottykohn

So I tried but it did not help. @mconnew @StephenBonikowsky. Error msg System.InvalidOperationException: 'The operation 'appendEmployeeGeoPunchByIDNum' could not be loaded because it specifies "rpc-style" in "literal" mode, but uses message contract types or the System.ServiceModel.Channels.Message. This combination is disallowed -- specify a different value for style or use parameters other than message contract types or System.ServiceModel.Channels.Message.'

mottykohn avatar Aug 19 '19 21:08 mottykohn

@mottykohn Sorry for the delay in getting back to you. We are having to focus on some other high priority work so we haven't been able to follow-up on this. It may be a little while before we can get to it.

StephenBonikowsky avatar Sep 10 '19 00:09 StephenBonikowsky

@hurrk, on a .NET Framework application, can you try using "Add Service Reference" and see if you get the same error on .NET Framework? The problem is that your service contract has been generated with a MessageHeaderAttribute on one of the parameters and that's not supported when using RPC encoded style contracts.

I've recently run into this issue as well. Here's an example .wsdl: http://webservice.dkvistun.is/DemoDev/dkwsitemscgi.exe/wsdl/IItemService

I can generate a client in .NET Framework that works by using 'Add Service Reference > Advanced > Add Web Reference" . It looks slightly different from the client generated in .NET Core as well.

Code that works against the web service in .NET Framework:

var client = new IItemServiceservice()
{
    BasicSecurityValue = new BasicSecurity()
    {
        Username = _config.DKServiceUsername,
        Password = _config.DKServicePassword
     }
};

var customer = client.GetCustomer(idnumber, null);

Code that doesn't work in .NET Core:

client.GetCustomer(new ServiceReference1.GetCustomerRequest
{
    BasicSecurity = new ServiceReference1.BasicSecurity
    {
        Username = _config.Username,
        Password= _config.Password
    },
    number = "...",
    opt = new ServiceReference1.TCustomerOptions() { }
});

The exception I get is the following (same as the original) one:

System.InvalidOperationException: 'Message CreateTimeClockTransactionRequest must not have headers to be used in RPC encoded style.'

I can think of a couple of workarounds (wrapping the API with a .NET Framework API or sending a raw SOAP request that I construct) but I'm interested in whether you guys can/will look at this.

RagnarRa avatar Dec 02 '19 16:12 RagnarRa

@hurrk Thanks for the additional info. We are going to look into this. We just have to do some load balancing, but it is in our short list of issues to investigate.

StephenBonikowsky avatar Dec 02 '19 17:12 StephenBonikowsky

I have some kind of good news for you. I have this working in my local dev branch. There's some issues with the WCF Connected Services tool where it's generating the wrong code in some scenarios which will need to be addressed. That will be a lot bigger work item than my fix so I don't know when that will happen (and this doesn't work on .NET Framework currently either so it's not a regression). The connected services problem is only happening when the namespace is the default http://tempuri.org/ for the message header and/or message body. If you have an explicit namespace, I believe it should generate the correct output. It should be relatively easy to fix the generated code manually. I'll update this issue when I have the fix submitted for review.

mconnew avatar Jan 29 '20 00:01 mconnew

I've got a change in PR to allow using MessageHeader attribute. This should close some of the gap in functionality between the client created by "Add Web Reference" (for older Web Services clients) and WCF. If there's anything else needed to allow WCF to be clients for those older services, we'll try our best to close the gap.

mconnew avatar Feb 12 '20 00:02 mconnew

PR merged, closing.

StephenBonikowsky avatar Mar 02 '20 21:03 StephenBonikowsky

I have exact problem with https://aodws.attendanceondemand.com:8192/cc1.aew/wsdl/IAeXMLBridge Works with Web Reference and exact RPC message as above when I try in core

@mottykohn did you manage to use the AOD service with Net Core? I'm facing the same issue now :(

jbnone avatar Oct 30 '20 22:10 jbnone

@jbermudezcabrera Nope, I am running old .NET 4. I tried a couple of times to get back to it but could not figure it out.

mottykohn avatar Nov 01 '20 15:11 mottykohn

@jbermudezcabrera are you using the latest package version? If you are and are still getting the same exception message, can you provide the exception call stack? I'm not aware of any other places where this exception message is thrown from but I could be wrong.

mconnew avatar Nov 02 '20 19:11 mconnew

@jbermudezcabrera are you using the latest package version? If you are and are still getting the same exception message, can you provide the exception call stack? I'm not aware of any other places where this exception message is thrown from but I could be wrong.

@mconnew thanks for commenting, I'm using .Net Core SDK v3.1.403 with VS 2019 v16.7.7, here is the stack trace:

System.InvalidOperationException: Message getEmployeeTransferRatesByFileKeyRequest must not have headers to be used in RPC encoded style. at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.OperationReflector.LoadHeadersMapping(MessageDescription message, String mappingKey) at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.OperationReflector.CreateMessageInfo(MessageDescription message, String key) at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.OperationReflector.EnsureMessageInfos() at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.EnsureMessageInfos() at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.OperationReflector.get_Request() at System.ServiceModel.Description.XmlSerializerOperationBehavior.CreateFormatter() at System.ServiceModel.Description.XmlSerializerOperationBehavior.System.ServiceModel.Description.IOperationBehavior.ApplyClientBehavior(OperationDescription description, ClientOperation proxy) at System.ServiceModel.Description.DispatcherBuilder.BindOperations(ContractDescription contract, ClientRuntime proxy, DispatchRuntime dispatch) at System.ServiceModel.Description.DispatcherBuilder.ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime clientRuntime) at System.ServiceModel.Description.DispatcherBuilder.BuildProxyBehavior(ServiceEndpoint serviceEndpoint, BindingParameterCollection& parameters) at System.ServiceModel.Channels.ServiceChannelFactory.BuildChannelFactory(ServiceEndpoint serviceEndpoint, Boolean useActiveAutoClose) at System.ServiceModel.ChannelFactory.CreateFactory() at System.ServiceModel.ChannelFactory.OnOpening() at System.ServiceModel.Channels.CommunicationObject.System.ServiceModel.IAsyncCommunicationObject.OpenAsync(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.OpenAsyncInternal(TimeSpan timeout) at System.Runtime.TaskHelpers.WaitForCompletion(Task task) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open() at System.ServiceModel.ChannelFactory.EnsureOpened() at System.ServiceModel.ChannelFactory1.CreateChannel(EndpointAddress address, Uri via) at System.ServiceModel.ChannelFactory1.CreateChannel() at System.ServiceModel.ClientBase1.CreateChannel() at System.ServiceModel.ClientBase1.CreateChannelInternal() at System.ServiceModel.ClientBase1.get_Channel() at AodWebService.AeXMLBridgeClient.AodWebService.IAeXMLBridge.getPayPeriodClassesAsync(getPayPeriodClassesRequest request) in D:\Work\Company\Client\Projects\project\Project.Services\Connected Services\AodWebService\Reference.cs:line 38432 at AodWebService.AeXMLBridgeClient.getPayPeriodClassesAsync() in D:\Work\Company\Client\Projects\project\Project.Services\Connected Services\AodWebService\Reference.cs:line 38438 at Project.Services.Impls.Aod.AodService.GetDataAsync(Int32 clientId) in D:\Work\Company\Client\Projects\project\Project.Services\Impls\Aod\AodService.cs:line 37

jbnone avatar Nov 02 '20 23:11 jbnone

I faced the same exception with https://www.openair.com/wsdl.pl .Net Core 3.1, VS 2019 16.7.2

Message readRequest1 must not have headers to be used in RPC encoded style. at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.OperationReflector.LoadHeadersMapping(MessageDescription message, String mappingKey) at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.OperationReflector.CreateMessageInfo(MessageDescription message, String key) at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.OperationReflector.EnsureMessageInfos() at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.EnsureMessageInfos() at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.OperationReflector.get_Request() at System.ServiceModel.Description.XmlSerializerOperationBehavior.CreateFormatter() at System.ServiceModel.Description.XmlSerializerOperationBehavior.System.ServiceModel.Description.IOperationBehavior.ApplyClientBehavior(OperationDescription description, ClientOperation proxy) at System.ServiceModel.Description.DispatcherBuilder.BindOperations(ContractDescription contract, ClientRuntime proxy, DispatchRuntime dispatch) at System.ServiceModel.Description.DispatcherBuilder.BuildProxyBehavior(ServiceEndpoint serviceEndpoint, BindingParameterCollection& parameters) at System.ServiceModel.Channels.ServiceChannelFactory.BuildChannelFactory(ServiceEndpoint serviceEndpoint, Boolean useActiveAutoClose) at System.ServiceModel.ChannelFactory.CreateFactory() at System.ServiceModel.ChannelFactory.OnOpening() at System.ServiceModel.Channels.CommunicationObject.<System-ServiceModel-IAsyncCommunicationObject-OpenAsync>d__79.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at System.ServiceModel.Channels.CommunicationObject.<OpenAsyncInternal>d__78.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at System.Runtime.TaskHelpers.WaitForCompletion(Task task) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open() at System.ServiceModel.ChannelFactory.EnsureOpened() at System.ServiceModel.ChannelFactory1.CreateChannel(EndpointAddress address, Uri via) at System.ServiceModel.ChannelFactory1.CreateChannel() at System.ServiceModel.ClientBase1.CreateChannel() at System.ServiceModel.ClientBase1.CreateChannelInternal() at System.ServiceModel.ClientBase1.get_Channel()`

nguyenluthuy249 avatar Apr 29 '21 00:04 nguyenluthuy249

I just double checked, and this is due to using an older version of the WCF nuget packages. Make sure you are using the latest version, which is currently 4.8.1 of the System.ServiceModel.XXXXXX packages.

mconnew avatar Apr 29 '21 18:04 mconnew

I just double checked, and this is due to using an older version of the WCF nuget packages. Make sure you are using the latest version, which is currently 4.8.1 of the System.ServiceModel.XXXXXX packages.

Thanks for your help. I updated the package to 4.8.1 and got a new exception

Header namespace mismatch in member SessionHeader of type OA.readRequest1. The header namespace found in the description is . The element namespace deduced by the formatter is http://namespaces.soaplite.com/perl. This mismatch can happen if the Namespace specified in XmlElementAttribute or XmlArrayAttribute does not match the namespace specified in the MessageHeaderAttribute or MessageHeaderArrayAttribute or the contract namespace.

I guess I have to manually modify the proxy class. Please advise

nguyenluthuy249 avatar Apr 29 '21 19:04 nguyenluthuy249

The problem you are seeing is that WCF in .NET Framework never fully supported some styles of soap services (which the .NET 2.0 Web Services implementation could produce), and as there was always the SoapClient from .NET 2.0 available, no resources were put into filling that gap. I've made some improvements to WCF Core to support these now that SoapClient isn't around, but some of the tooling still does the wrong thing, as it never needed to handle this situation before. This means that sometimes you hit this problem where the WCF Core runtime library can handle it if the contract is correct, but you have to manually fix up the contract. Thankfully the error message is helpful in this case and tells you what namespace you need to set on the attribute of the SessionHeader property of the readRequest1 class. You likely have an XmlElement attribute on the property, so you need to do something like this:

internal static class ContractConstants
{
    public const string SoapLitePerlNamespace = "http://namespaces.soaplite.com/perl";
}
public class readRequest
{
    
    [XmlElement(Namespace =  ContractConstants.SoapLitePerlNamespace)]
    public string SessionHeader { get; set; } // Might not be string, just for illustration
    /// Rest of class
}

mconnew avatar Apr 29 '21 19:04 mconnew

So far, we are converting our app from .Net Framework 4 to Core 3.1. Previously, we consume OpenAir SOAP service using Add Web Reference. However, this option was no longer available in Core. That's why we needed to use "Add Service Reference"

I was able to resolve the latest namespace issue with your suggestion. Then it threw a new exception

RPC Message servertimeResponse in operation servertimeWithTimezone has an invalid body name servertimeResponse. It must be servertimeWithTimezoneResponse

After updating the Wrapper name of this MessageContractAttribute from servertimeResponse to servertimeWithTimezoneResponse, it threw another exception: RPC Message servertimeResponse in operation servertime has an invalid body name servertimeWithTimezoneResponse. It must be servertimeResponse

I investigated and found out two Operations servertimeWithTimezone and servertime are using the same MessageContract servertimeResponse. I resolved this by cloning the class servertimeResponse and decorate the new one using servertimeWithTimezoneResponse in the Wrapper name. After that, I was able to successfully make a SOAP call to OpenAir.

Could you provide some insights about whether my fix is correct or it will cause further problems? Thanks

nguyenluthuy249 avatar Apr 29 '21 21:04 nguyenluthuy249

It looks like you have two separate but similar operations, servertimeWithTimezone and servertime. I suspect you are using the same return object for both operations because when you fixed servertimeWithTimezone to use servicetimeWithTimezoneResponse, your servertime operation broke. But each operation needs a differently named wrapper around the response. You need to duplicate your return wrapping object so each operation can have its own return type specifying the wrapper name.

mconnew avatar Apr 30 '21 01:04 mconnew

So this is the final problem that I do not know whether it's a bug in the tool. I was able to capture the SOAP message and we can see that the h:SessionHeader and q2:Array share the same id="id1" causing the server to response with Invalid Parameter Soap error. When using Adding Web Reference, the h:SessionHeader has id="h_id1 which is different from the one in q2:Array

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
	<s:Header>
		<h:SessionHeader id="id1" xmlns:h="http://namespaces.soaplite.com/perl" xmlns:q1="http://namespaces.soaplite.com/perl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
			<sessionId xsi:type="xsd:string">abcd</sessionId>
			<accessToken xsi:nil="true"/>
		</h:SessionHeader>
	</s:Header>
	<s:Body s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
		<q1:read xmlns:q1="https://connor-group-inc.app.openair.com/OAirService">
			<method href="#id1"/>
		</q1:read>
		<q2:Array id="id1" q2:arrayType="q3:ReadRequest[1]" xmlns:q2="http://schemas.xmlsoap.org/soap/encoding/" xmlns:q3="http://namespaces.soaplite.com/perl">
			<Item href="#id2"/>
		</q2:Array>
		<q4:ReadRequest id="id2" xsi:type="q4:ReadRequest" xmlns:q4="http://namespaces.soaplite.com/perl">
			<method xsi:type="xsd:string">equal to</method>
			<fields xsi:nil="true"/>
			<attributes href="#id3"/>
			<type xsi:type="xsd:string">Invoice</type>
			<objects href="#id4"/>
		</q4:ReadRequest>
		<q5:Array id="id3" q5:arrayType="q6:Attribute[1]" xmlns:q5="http://schemas.xmlsoap.org/soap/encoding/" xmlns:q6="http://namespaces.soaplite.com/perl">
			<Item href="#id5"/>
		</q5:Array>
		<q7:Array id="id4" q7:arrayType="q8:oaBase[1]" xmlns:q7="http://schemas.xmlsoap.org/soap/encoding/" xmlns:q8="http://namespaces.soaplite.com/perl">
			<Item href="#id6"/>
		</q7:Array>
		<q9:Attribute id="id5" xsi:type="q9:Attribute" xmlns:q9="http://namespaces.soaplite.com/perl">
			<name xsi:type="xsd:string">limit</name>
			<value xsi:type="xsd:string">1</value>
		</q9:Attribute>
		<q10:oaInvoice id="id6" xsi:type="q10:oaInvoice" xmlns:q10="http://namespaces.soaplite.com/perl">
			<number xsi:type="xsd:string">1</number>
		</q10:oaInvoice>
	</s:Body>
</s:Envelope>

nguyenluthuy249 avatar May 02 '21 18:05 nguyenluthuy249