WCF Soap Services without Soap Action - c#

I have an existing soap client who communicates with a soap service without using the soap action attribute. Now, we have recently substituted this soap service with a C# WCF Service which requires a soap action by default.
When I import the WSDL again, there is no problem. But, I don't want to regenerate the soap client because of backward compatible reasons. This afternoon I found an article with solves my problem: http://spikesoftware.azurewebsites.net/?p=151#comment-396784
The problem now is that my C# client can't invoke most of the soap actions. I can't find out the reason why this is not working anymore.
The error I received is the following:
Message:
System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]
: Error in deserializing body of request message for operation
'GetWorkshops'. OperationFormatter encountered an invalid Message
body. Expected to find node type 'Element' with the name
'GetWorkshops' and namespace 'http://tempuri.org/'. Found node type
'Element' with name 'GetWorkshops_V2' and namespace
'http://tempuri.org/'
The operation contract for these two methods like this:
[OperationContract(Action = "GetWorkshops", Name = "GetWorkshops")]
WorkshopResponse GetWorkshops(<some parameters>)
[OperationContract (Action = "GetWorkshops_V2", Name = "GetWorkshops_V2")]
WorkshopResponse_V2 GetWorkshopsV2(<some parameters>)
Can someone help me?

You can try out a couple of things,
Please use wsHttpBinding instead of basicHttpBinding
Generate a client proxy using svcutil

Related

WCF ServiceModel.CommunicationException when called internally

I added the reference of an external wcf service to my project. I can consume this service normally, but trying to consume internally (on the same server as the service is exposed to) I am getting the error below:
System.ServiceModel.CommunicationException: Error in deserializing body of reply message for operation 'RETMALHA'. OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'RETMALHARESPONSE' and namespace 'http://200.XXX.XXX.XX:81/'. Found node type 'Element' with name 'RETMALHARESPONSE' and namespace 'http://192.168.XXX.XXX:81/' ---> System.Runtime.Serialization.SerializationException: OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'RETMALHARESPONSE' and namespace 'http://200.XXX.XXX.XX:81/'. Found node type 'Element' with name 'RETMALHARESPONSE' and namespace 'http://192.168.XXX.XXX:81/'
Given this message I manually manipulated the automatically generated "References.cs" file and changed the address of the Namespaces that had 200.XXX.XXX.XX:81 to 192.168.XXX.XXX:81. After this change internally began to work, but externally no longer works.
This service was not created by me, I am just consuming. And the application I'm developing will consume internally and externally.
Is there anything that I could make the client side flexible? Or do I have to talk to the service owner? What's wrong?
WCF‘s SOAP envelope needs to serialize and deserialize data as it is transmitted between the client-side and the server. This requires that for custom data types (data conventions), it is important to ensure that the data type has the same fully qualified name on both the client-side and the server-side, including its namespace attribute. In general, this values should be constant for a particular endpoint address (when we call the service by adding service reference), Please make sure you use the right service endpoint to add the service.
Feel free to let me know if there is anything I can help with.

Consume SOAP webservice with GET instead of POST

I need to call an external SOAP webservice over HTTP.
I have the WSDL file and added it in Visual Studio via 'Add service reference'. Visual studio then added a number of files, in the reference file i can find this:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="Service.IService")]
public interface IService {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService/Function", ReplyAction="http://tempuri.org/IService/FunctionResponse")]
namespace.Service.ExecuteFunctionResponse ExecuteFunction(namespace.Service.FunctionRequest request);
}
With additionaly the async version of this call and the objects for sending an receiving, etc.
To call the service I added the folowing code:
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("the address");
serviceChannel = new ServiceClient(binding, endpointAddress).ChannelFactory.CreateChannel();
Response response = serviceChannel.ExecuteFunction(new Request(...));
This results in me getting an exception, error 405 method not allowed.
So it appears I must use a HTTP GET request instead of the default POST request. But i cannot find where this can be altered in with this way of working.
So, where can i set the HTTP method for this call to a webservice?
SOAP services are using HTTP POST because they exchange XML messages (which tend to be complex) and cannot be transferred in a query string.
Are you sure that you must use HTTP GET? Maybe the error you are receiving "405 method not allowed" is caused by some bad configuration.
I would double check the SOAP endpoint URL is set correctly and check that there are no additional security requirements needed.
EDIT
In past, there was a practice to create ASP.NET Web Services which would accept GET as well. But they wouldn't expect XML messages. Instead, you would have to pass all parameters in a querystring. For example: https://foo.bar/service.asmx/Func?param1=X&param2=Y (where param1 and param2 are the expected parameters).
This way it is possible to call a WebService without a need for WSDL and using GET method. You can achieve it by using HttpClient for example.
The downside of this approach is that you will have to deal with plain data instead of objects.
I hope it might help.

Generate service based on WSDL, that produces nearly same WSDL

I need to create a SOAP webservice that will be consumed by a partnering company. The partnering company has supplied an example of a WSDL file for the service, as there are some naming conventions for methods and objects that must match theirs. It is a fairly simple webservice, with an execute method that takes an array of NameValue objects as input, and returns a boolean. This WSDL file is clearly for a SOAP webservice written in Java.
I have used svcutil to generate classes using their WSDL, to use for my own webservice, which is written in C# as a WCF service. The service is deployed, and I can call it using SOAPUI and get the expected results.
The partnering company however tells me that the WSDL for my webservice doesn't match the expected, and that my service cannot be called from their system. The error they are getting on their end is:
The message with Action 'execute' cannot be processed at the receiver,
due to a ContractFilter mismatch at the EndpointDispatcher. This may
be because of either a contract mismatch (mismatched Actions between
sender and receiver) or a binding/security mismatch between the sender
and the receiver. Check that sender and receiver have the same
contract and the same binding (including security requirements, e.g.
Message, Transport, None).
When inspecting the WSDL produced by my WCF service, I see that some of the names are not the same as in their WSDL file. For example, the request message for the execute operation in their WSDL is called request but in my WSDL it is now called IMyService_execute_InputMessage.
How can I change my WCF service, so that the resulting WSDL matches that of the partnering company's WSDL?

WCF Service Trace shows UriFormatException

I'm trying to make a WCF service that will be consumed by other parties by passing a SOAP request to the service. The client requires me to handle a set of FaultExceptions that could happen during the interaction.
This includes that if the client send a malformed Uri in the SOAP request [wsa:To] element, that is if the client for example send a request contains the following:
<wsa:To>http//:this.is.invalid/address</wsa:To>
I should be able to throw a specific FaultException. I tried to implement the IDispatchMessageInspector to capture the SOAP request before it reach the operation but when the client send a request contains a bad Uri like in the above example, the AfterReceiveRequest is not called and so I can NOT handle this type of error.
I couldn't find the error until I've enabled the trace logging for my WCF service and I'm the error
System.UriFormatException, System, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089<br><br>with the description
<br><br>Handling an exception. Exception details:
System.UriFormatException: Invalid URI: The URI scheme is not valid.
The question is how and where can I catch this exception in the Code? Thanks in advance,
The soap header wsa:To should contain the address of the intended receiver of the message. WCF client-side framework enforces this by using the service endpoint address as the value for the wsa:To header element. I'm not sure whether the WCF service-side framework enforces validation of this element since it has already ready received the soap message.
You're seeing the 400 HTTP error because the WCF client is attempting to sent a soap message to an invalid service endpoint. To properly test an invalid wsa:To value you need code that will create the soap XML with an invalid wsa:To value but sent to the correct service endpoint.
If WCF doesn't validate this value, you're approach of using an implementation of the IDispatchMessageInspector should work. Otherwise, if WCF throws an exception before the IDispatchMessageInspector implementation is called then you may need to implement a IErrorHandler endpoint behavior to catch this kind of "in the plumbing" exception. See this great blog post for information on how to implement and configure it.

WCF proxy generated from WSDL, proxy method returns null

I've generated a WCF proxy from a WSDL file, but now when I call the proxy methods, they return null. I've enabled message logging, and can see that the messages from the server are correctly returned.
I've checked the answer of this question, but in my case at least the name of the returned object was the same in the message and in the WSDL. I still believe the problem has to do with the WSDL file, since it is not fetched the usual way through the "?wsdl" URL (it is a 3rd party webservice), but was given separately.
The return type of the method is just a string.
Has anyone else had similar problems, and what was the corresponding solution, if any? What is the most likely source of the problem?
Re-edit:
It is a RPC/Encoded web service. As written, I can see the SOAP response through message logging, but WCF seems not to be able to parse the information.
The message part of the response from the service looks like this:
<ns1:ServiceResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="the target namespace">
<ns1:ReturnValue xsi:type="xsd:string">
However, when inspecting the outgoing message from my client, it's different:
<ns1:ServiceRequest soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="the target namespace">
<RequestValue xsi:type="xsd:string" xmlns="">
So maybe the proxy expects the response to have the same namespace structure, and thus fails to parse it.
I've tried to change the type attribute to element in the wsdl message definitions, and adding some new elements in the types part of the wsdl definition, but then the svcutil chokes when generating the proxy, complaining that there's a clash between the inferred style document and specified style rpc.
From the WSDL specification, section 3.5:
If use is encoded, then each message part references an abstract type using the type attribute.
But then I'm a bit confused, since it doesn't seem to have been a problem in this question. What would be needed to make a similar change, with the restriction that it is a RPC/encoded service?
You'll have to give specifics about the Java service in order to resolve this. However, I suspect that the Java service is using message parts defined with the type attribute. These do not conform to WS-I Basic Profile 1 because there is ambiguity about which namespace should be used for the elements of the message. Some services will use the namespace of the type, while others will (correctly) use the namespace of the web service itself.
Using the element attribute removes the ambiguity, and is therefore preferred.
Please post a snippet of the WSDL containing one of the messages you're having trouble with. When you then compare the definition of the message with what you're seeing on the wire, and then compare that to the details of the proxy class that's meant to consume the message, I believe you'll see what I mean. The proxy class is expecting one namespace, but on the wire, a different namespace is being used.
We have had something similar when using a WCF client against a WSDL from a Java web service.
Our problem was that we could not see the data that was coming back from the service, it looked like the data was missing.
However, when we looked at what was going over the wire, the data was there.
The problem was that the WSDL had many types that inherited from other types. By default we would only see the information in the base type.
The solution was to cast the object to the type we expected, then all the fields appeared.

Categories

Resources