SOAP with external namepaces deserializes to NULL - c#

I'm implementing a client to a SOAP-service, which I don't have access to. Since I'm a bit of a newcomer, I really don't have much experience with SOAP, so I went with the default approach of adding the Service Reference via Visual Studio 2017, configuring the Service via config-file and then hope it works.
Unfortunately, whenever I call the service, I get a NULL-response. Searching a bit, it seems like some Namespace problems. In fact, the WSDL has a lot of defined external namespaces, like:
xmlns:eCH-0011="http://www.ech.ch/xmlns/eCH-0011-f/8"
I thought, the proxy generator would take of this, but for example when I use the http://webservicestudio.codeplex.com/, I get a namespace exception like:
Schema parsing error In diesem Schema ist Namespace
'http://www.ech.ch/xmlns/eCH-0044-f/4' nicht für den Verweis
verfügbar.
Which is german and means the namespce is not avaliable for a reference.
I tried to create the WSDL dynamically by calling the service with the "svc?wsdl" prefix as well as received a WSDL from the developers, but both are not working.
I also used Fiddler as proxy, and I see in the response I would get correct XML, but yet, in the code I don't get any error nor other feedback what the problem is.
Is it generally not possible to have external namespaces, or am I configuring something wrong here? I'm currently trying to kindahow sneak between the incomming data and the deserialization, but didn't have any luck so far. Sadly, there are not much information around as far as I seached for it.
Playing around: I played around further, implementing a IClientMessageInspector and a IEndpointBehavior, where I can debug the incoming message. This seems fine, so it has to be the SOAP-formatter, which causes problems here. Unfortunately, I still can't get an Exception, yet it's always null.

Related

How to figure out exactly where the error is in the deserialization of WCF SOAP XML response?

Apologies if this has been asked before but it seems I cannot find the answer.
I am trying to consume a SOAP Web Service using WCF. I've used Visual Studio 2015's Add Service Reference to add the service reference and generate all code.
The service call fails with the following CommunicationException error:
System.ServiceModel.CommunicationException : Error in deserializing body of reply message for operation 'XYZ'.
---- System.InvalidOperationException : There is an error in XML document (2, 979).
-------- System.FormatException : Input string was not in a correct format.
I understand the error; I understand that something (an element value, probably) in the XML response document cannot be deserialized according to what the svcutil's generated code dictates.
I am logging the XML response document. Also, I am comparing it with the SoapUI response and they both look identical.
SO how can I figure out exactly where the problem is in the XML document? Is there any method, technique or trick to step through the deserialization process and pinpoint the faulty bit? It is a rather long XML document ...
IMHO, at this point the WCF behaves like a black box that I cannot look inside it.
TIA,
Turn on WCF Trace:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/diagnostics/tracing/configuring-tracing
Use the following application to view the results:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/service-trace-viewer-tool-svctraceviewer-exe
Well, it seems one cannot really find exactly where such a deserialization error lies. Things get even worse if the service developer is not the same person as the service client developer.
In my case, the error was due to a mismatch of a data type between the service and the generated client code. The origin of the problem was the erroneous XSD. In order to find the error, I had to contact the service developer who managed to locate it.
Generally speaking, this is one of those things that make you feel you are losing control over your code; much like that point in a project when you want to look the source code of a library but you just can't because you don't own it. This is something all developers who decide to work on web services consuming project should be aware of.
For debugging, you can use Fiddler2 easily to capture any web traffic, including the full xml of a SOAP request/response (and it even handles SSL easily, unlike Wireshark)
For logging... I wish I knew. Sorry.
Also, dupe of In C#, How to look at the actual SOAP request/response in C#

Is there a way to push NamepaceMappings programmatically from the WCF host?

I have a WCF service that requires me to add the folowing to Reference.svcmap
<NamespaceMappings>
<NamespaceMapping TargetNamespace="http://schemas.datacontract.org/2004/07/System.DirectoryServices"
ClrNamespace="System.DirectoryServices" />
</NamespaceMappings>
If I don't have that line I get the following error:
Warning 1 Custom tool warning: Cannot import wsdl:portType
Detail: An exception was thrown while running a WSDL import extension:
System.ServiceModel.Description.DataContractSerializerMessageContractImporter
Error: ISerializable type with data contract name 'DirectoryServicesCOMException'
in namespace 'http://schemas.datacontract.org/2004/07/System.DirectoryServices'
cannot be imported. The data contract namespace cannot be customized for
ISerializable types and the generated namespace
'DomainManagement.Console.UserManagementProxy' does not match the required CLR
namespace 'System.DirectoryServices'. Check if the required namespace has been
mapped to a different data contract namespace and consider mapping it
explicitly using the namespaces collection.
XPath to Error Source:
//wsdl:definitions[#targetNamespace='http://example.com/v1']/wsdl:portType[#name='IUserManagement']
I also know having a common DLL between the client and server will also solve the issue but I do not want to have to require any client to also have the accompanying DLL to communicate with the service.
I understand the issue, and the fix (both dll and editing the file). What I would like to know is: Is there anything I can do on the Host side so every client that subscribes to this service does not need to any extra configuration of the service after generating the proxy in visual studio? (i.e. Using SvcUtil and using the /n:http://schemas.datacontract.org/2004/07/System.DirectoryServices,System.DirectoryServices parameter is not a preferred option)
I think this is simply down to the fact that some types "don't serialize well". Trying to pass a NameValueCollection across WCF (prior to VS2010) produced exactly the same error as you are seeing, despite it being serializable. Another one that I've seen crop up from time to time is the SqlException (see here).
Alas I'm not aware of any server-side solutions. I find that providing clients with a "service interface" DLL to be the cleanest approach - it avoids having to generate client-side code via svcutil/add service reference, but you seem to have your reasons for not doing this. The alternative would be to refactor your server-side code to avoid passing around a DirectoryServicesCOMException. You could try Googling the "NameValueCollection WCF serialization" issue and see if any of the suggested workarounds from back then might be applicable to your scenario. I suspect not though, as this was caused by the way it implemented certain interfaces internally.

Mapping a bad wsdl

Im attempting to interact with another company's web service via WSDL.
I've imported it into VS2010 as a service reference, I can make request just fine. The problem is, the return types are strings (of xml). Now I'm fairly new to the WSDL deal, but from what I've read there should be return types in the contract and then the service reference would auto-magically generate classes for me.
How do I remedy this?
I suppose I could map the strings of XML, if so, can someone please
show me a nice example? As I have tried with no avail.
Could I tell the web service to use a return type that I specify?
Or, do i have the wrong idea about WSDL? And if so, could someone please explain inconsistencies in my understanding?
Your basic idea is correct, having a service wsdl should define the return and input objects to the service operations. The service provider might have a valid reason for just returning you strings or maybe he just didn´t know better.
For you the WSDL is the final frontier, unless your business partner is able to provide a new one you cannot change the service interface, so you have to deal with the XML strings.
Check out XMLDocument, it offers the Load() method accepting a string. If it fails, chances are you´re missing an XSD or you dont have a valid/wellformed xml document contained inside the string. In both cases it´s your business partner who has to correct the error or provide further information.

Customizing the xmlns:a= tag in a soapresponse from WCF

I'm creating a service to respond to calls.
However the client(not written by me) cannot read the response.
What we have located is that this seems to be due to th missmatching namespace in the
xmlns:a="http://schemas.datacontract.org/2004/07/MyProject.Classes"
Is there anyway to override this namespace?
I'm rather sure it is.
The [ServiceBehavior] tag has the "http://correctnamespace.com" NameSpace
The BindingNameSpace in the app.config has the "http://correctnamespace.com" Namespace
The [ServiceContract] has the "http://correctnamespace.com" Namespace
I've looked at the OperationsContract to see if I can locate it but without luck.
the namespace needs to be "http://correctnamespace.com"
Below is a full example of the Upper part of the SOAPresponse
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<getAddressResponse xmlns="http://correctnamespace.com">
<getAddressReturn xmlns:a="http://schemas.datacontract.org/2004/07/MyProject.Classes" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:PropertyChanged i:nil="true" xmlns:b="http://schemas.datacontract.org/2004/07/System.ComponentModel"/>
<a:addressField>Happystreet 21</a:addressField>
I hope someone can help me sort this ut ASAP.
Added information
The service is created to fit he client.
The client is predesigned and the service is created based on a WSDL file provided from the client creator.
Also note that the client cannot be modified. :(
I have a couple suggestions.
First, assuming that the server side code sand stubs are all correct and functioning properly, ask the client to regen the client side stubs. It is possible that somehow the stub they are using is old or has been modified.
Second, if the serverside is also not working properly I recommend recreating your WSDL from scratch. Proper SOAP coding is WSDL to code creation. So if your WSDL was generated by a tool it will have a certain naming convention and while you can manually change things like your xmlns, if you miss one (which is what it sounds like happened) it will mess up your code. So go back and make the WSDL from scratch and generate the code classes from the WSDL that way you can name everything the way you want it to be named.
Based on the added information, I again have two suggestions.
First, is that you will have to go in and manually change the soap response AddressReturn namespace and follow the chain so that any references to the aforementioned response has the correct namespace. It will be tedious and annoying, but you could program an xml parser that can find any references to such field and make the necessary changes in both the schema and the WSDL.
Second is to use the WSDL provided to you by the client in order to create your own WSDL that will work with the client but has the naming conventions that you want incorporated. WSDL first coding can be done this way and is sometimes recommended because it provides the skeleton that you follow in creating and modifying to make it your own and fit your needs.
Solved by copying all the classed from the WSDL and made DataContracts of them instead, in this it's possible to define the NameSpace just like for the ServiceContract.
[DataContract(Namespace = "http://correctnamespace.com")]
public class Amount
{
Thanks for evryone who took timeto help me solve his.

WCF error service error message with shared classes

Source code:
http://code.google.com/p/sevenupdate/source/browse/#hg/Source/SevenUpdate.Base
SevenUpdate.Base.Sui cannot be used since it does not match imported DataContract. Need to exclude this type from referenced types.
Now I tried unchecking reuse reference types and I was able to get my project to compile. but when sending a collection from the client it was never received or couldn't be deserialized on the server end.
I really need this to work. Any help would be appreciated, the fullsource code is provided by google code.
I didnt download the source and build it, but could it be that you are missing DataContract on this class? Sui class has a property of type Sua as DataMember so it will need to be serialized as well. It looks like this in your code currently
[ProtoContract, ]
[KnownType(typeof(ObservableCollection<LocaleString>))]
public class Sua
What would I need to do to reproduce this error? The first bit (about matching data-contract) sounds like WCF isn't very happy with you, which suggests you have two similar (but different) contracts "in play". If you are re-using the types from a shared library this shouldn't be a problem.
If you do end up excluding the types (and having a different model at the client and server) then it can get a bit tricker, since "mex" doesn't guarantee the positions will remain intact (and indde, they regularly change) - but you can fix this in a partial class, by using a few [ProtoPartialMember(...)] against the type (not pretty but it works).
But I stress - the main problem here seems to be WCF; if that isn't happy such that the code doesn't codegen / compile etc, then my hands are fairly tied (since it won't get as far as talking to protobuf-net).

Categories

Resources