Handle unknown soap message from WCF - c#

I have a client generated using SVCUTIL from WSDL + XSD in C# .net console app. All fine but for some logical error handling purpose, client may receive a response message, which is not defined in WSDL hence deserialization & will fail but method does not throw exception but returns null.
Is there any generic way to handle this situation or I define a fault/error message xsd(for soap message returned by server) and in case of null response, handle/deserialize the message.
PS: My remote service can not throw a fault exception for logical errors.(yeah a bit of blockage there).

WSDL is contract. It is same like if you have two objects and defined interface between them. If the first object calls the operation on the second object it expects return value defined by interface. If we would use some non-strongly typed language the second object would be able to return different type of return value and the first object would fail because of unexpected error.
Programming languages have approach to solve this - in case of .NET you would use object type as return value and you would always have to manually investigate what type did you receive and how to handle the return value. In case of WCF we also have such high level type - System.ServiceModel.Channels.Message but you really don't want to use it because in such case you will have to build SOAP request manually and parse incoming responses manually.
As a side note in web services single request type has always single response type and zero or more error types (which are SOAP faults). If you have a service which returns different response types on single request type such service is not "valid" web service and cannot be described by WSDL. Because of that it also cannot be in strongly typed way provided by auto-generated WCF proxy.

Related

Why does a WCF web service not receive the client payload?

I have inherited a web service built to receive calls from a third party system, "System A". It was a POC that may not have any active functions calling it and I suspect it was only tested from SoapUI or the like and never from the application it was designed for.
When System A is configured to call it, the service is called but the payload, one complex-type parameter, is null.
I have two other web services written years ago that accept calls of the same type from the same function of System A. Pointing System A to either of these services results in the parameter being supplied. Contracts and WSDLs look very similar and the only variations I see (like differing namespaces) seem to vary between the two services that do work.
What would cause a web service to not receive the payload in the call?
Related, where should I look to find it? The parameter is getting dropped between System A calling and the web service code itself getting hit. I've checked the trace logs but see nothing that I recognize as useful.
namespace MyNamespace.StandardNoteReceiverService
{
public class StandardNoteReceiverService : IReceiveNoteService
{
public StandardNoteReceiverResponse ReceiveNote(ReceiveNoteData standardNoteReceiverRequest)
{
string x = standardNoteReceiverRequest == null ? "NULL" : "ok";
LoggingLib.Log($"Service called. Paramter status: {x}");
return NoteReceiverServiceLayer.ReceiveNote(standardNoteReceiverRequest);
}
}
}
which implements
namespace MyNamespace.StandardNoteReceiverService
{
[ServiceContract]
public interface IReceiveNoteService
{
[OperationContract]
StandardNoteReceiverResponse ReceiveNote(ReceiveNoteData standardNoteReceiverRequest);
}
}
It turned out to be the parameter naming. Once I changed the name of the parameter to be the same as the name used by the services that are working, it began receiving the data.
public class StandardNoteReceiverService : IReceiveNoteService
{
public StandardNoteReceiverResponse ReceiveNote(ReceiveNoteData NoteData)
{ ...
How did you build “System A”? Is it a WCF Web HTTP service or an ancient soap web service? How does the client call the service and send the parameter? I think it may be that the format of the parameters sent by the client is incorrect. In the Rest-style service created by WCF, using complex objects as parameters to pass data may not always receive the value of the parameter on the server because of the format of the parameter.
Get the object is null using JSON in WCF Service
While in the WCF SOAP web service, the invocation is completed with a client proxy, the parameters are strong-typed. If the server always gets null, it might be caused by other issues.
I suggest you create a minimal, producible example so that I can try to offer a workaround instead of offering speculation of this issue here.
Feel free to let me know if the problem still exists.

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?

Can unpredictably typed arguments be handled in a WCF service?

I'm relatively new to WCF services, so I apologize in advance if I'm missing the obvious. My business uses EasyPost as our shipping solution, and I've written a WCF service to handle the shipping status webhook calls from EasyPost, described here: https://www.easypost.com/docs/webhooks
Briefly, EasyPost sends an update object as JSON via POST. The problem is that it sends several different types of (non-configurable) updates to the same service method, and I'm finding it difficult to write a DataContract that encompasses all the possibilities. For example, if the argument it sends is a tracking number update, update.result.status will be a string value; if it's a batch status update, update.result.status will be an object. It's a bit of a mess.
I tried handling just the update type that I care about and returning a 400 status code on the others, but EasyPost interprets that as an outage and drops my service as a webhook endpoint.
From what I've read, it looks like I could abandon the comforts of a Data Contract in favor of using a System.ServiceModel.Channels.Message parameter as a catch-all, then parse the message manually. That doesn't strike me as a wise/clean solution, though.
I'd be grateful for any alternatives.
This is probably not the best way I could have handled this, but it works.
I have an HTTP Module that identifies whether the incoming request is for the proper service method, and if so, converts the ContentType header from "application/json" to "text/plain".
My service method accepts the content body as a System.IO.Stream parameter. By converting the stream to a byte[] and then to a string, I end up with the raw JSON string sent by EasyPost.
After that, it's just a matter of using Newtonsoft.Json to attempt to deserialize the JSON string into the expected Type.
Even if the deserialization fails, I can still log the data and send a success response to the caller. That's good enough for my purposes.

ServiceStack sessions doesn't work when using JsConfig.ExcludeTypeInfo

In the AppHost I'm setting JsConfig.ExcludeTypeInfo=true; to prevent the type being serialized into the response (I'm using anonymous types in some web service responses).
Everything works fine authenticating to /api/auth/credentials but when there is a request to a secured web service the GetSession() extension method fails to get the IAuthSession from ICacheClient because is trying to deserialize to an interface (IAuthSession) and in Redis the JSON doesn't have type information because of the JsConfig.ExcludeTypeInfo setting so the serializer doesn't know which concrete type to use.
If you use a CustomAuthUserSession and have
JsConfig.Init(new Config {
ExcludeTypeInfo = true
});
The solution is to enable it for the types that need it, in this case:
JsConfig<CustomAuthUserSession>.IncludeTypeInfo = true;
This is happening because ServiceStack lets you use and persist your own Custom UserSession it needs to persist that __type info with the payload to know what concrete type to dehydrate it into.
Supporting arbitrary responses
This is fairly rare as we only need to do this when a DTO can support holding arbitrary types, basically when using object, interfaces or abstract properties (i.e. we can't infer the type from the class definition). The only other place this exists in ServiceStack is in the MQ Message<T> type which allows persisting of any arbitrary body.
Use loose-typed data structures instead of anonymous types
By default, ServiceStack only adds the added __type info when it's required, although ideally you shouldn't be using anonymous types in service responses which requires deviating from the default configuration and the "pit of success" development that ServiceStack encourages.
Using a loose-typed data structure like Dictionary or List is preferred for unstructured data as anonymous types basically prevent your DTO's from being deserializable, and prevents clients from having any idea of what the service ultimately returns - which will break anything that relies on your services from being statically inferable, e.g. XSDs/WSDLs/SOAP.

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