views:

61

answers:

1

Hi all,

My team is tasked with getting several in-house developed .NET client applications to connect to some new Java web services. The Java web service is a third party, vendor supplied WSDL file that our team has a limited ability to modify/control...meaning we probably have the power to request our vendor to make slight tweaks to the WSDL, but major changes would probably be either unfeasible or difficult to request.

That said, we are attempting to utilize WCF/.NET 4.0 to generate the .NET proxy class files we need on the client side. The proxy client class file generation process executes without issues.

The problem is when we attempt to use the proxy class file in a client app. I have verified through the web trace tool, Fiddler, that the raw SOAP message request fails to get sent across the wire to the server.

The specific .NET exception message I get when attempting to call the web service method in question, looks like this:

System.InvalidOperationException was unhandled Message=XmlSerializer attribute System.Xml.Serialization.XmlAttributeAttribute is not valid in baseLanguage. Only XmlElement, XmlArray, XmlArrayItem, XmlAnyAttribute and XmlAnyElement attributes are supported when IsWrapped is true. Source=System.ServiceModel

When I examine the .NET autogenerated proxy class file, Reference.cs, I noticed that the request and response messages for my web service method looks something like this:

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="QueryPBOT_MXWO_OS", WrapperNamespace="http://www.ibm.com/maximo", IsWrapped=true)]
public partial class QueryPBOT_MXWO_OSRequest {

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=0)]
    public ConsoleApplication7.wsMaximo.PBOT_MXWO_OSQueryType PBOT_MXWO_OSQuery;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=1)]
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string baseLanguage;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=2)]
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string transLanguage;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=3)]
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string messageID;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=4)]
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string maximoVersion;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=5)]
    [System.Xml.Serialization.XmlAttributeAttribute()]
    [System.ComponentModel.DefaultValueAttribute(false)]
    public bool uniqueResult;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=6)]
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="positiveInteger")]
    public string maxItems;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.ibm.com/maximo", Order=7)]
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="integer")]
    [System.ComponentModel.DefaultValueAttribute("0")]
    public string rsStart;

    public QueryPBOT_MXWO_OSRequest() {
    }

    public QueryPBOT_MXWO_OSRequest(ConsoleApplication7.wsMaximo.PBOT_MXWO_OSQueryType PBOT_MXWO_OSQuery, string baseLanguage, string transLanguage, string messageID, string maximoVersion, bool uniqueResult, string maxItems, string rsStart) {
        this.PBOT_MXWO_OSQuery = PBOT_MXWO_OSQuery;
        this.baseLanguage = baseLanguage;
        this.transLanguage = transLanguage;
        this.messageID = messageID;
        this.maximoVersion = maximoVersion;
        this.uniqueResult = uniqueResult;
        this.maxItems = maxItems;
        this.rsStart = rsStart;
    }
}

I know that people reading this post will want to see the actual WSDL file we're trying to consume, but it is quite large, and I'm concerned the sheer size of it would make pinpointing the error quite difficult.

I'm hoping that the autogenerated client proxy file and the .NET exception will help someone recognize this WCF Serialization issue.

We've confirmed from our Java vendor that the style of WSDL they generate is doc-literal. After doing some research on the internet, it appears that WCF, by default. translates WSDL files with doc-literal wrapped, and that this may explain, at least in part, why we're seeing this WCF serialization issue with the WSDL file.

I've discovered, through trial and error, that the following attribute decorator in the proxy class file is the culprit behind the serialization issue:

[System.Xml.Serialization.XmlAttributeAttribute()]

If I comment out all instances of this attribute in the proxy class file and rerun my client app, the SOAP message successfully gets sent across the wire and I get a valid web service response come back from the server.

This fix is better than nothing, but I would very much prefer a solution that doesn't require myself or anyone on my team to constantly tweak these .NET autogenerated proxy class files.

I would like to know if there is something I can do, either through the various WCF tools or by modifying the WSDL file, that prevents that [System.Xml.Serialization.XmlAttributeAttribute()] from being applied to my request and response object properties?

Or at least a high level description of WHY we are seeing this serialization behavior in .NET with the Java WSDL file?

thanks in advance, John

+1  A: 

Based on generated code it looks like your Java service expects request like:

<s:Envelope xmlns:s="...">
  ...
  <s:Body>
    <QueryPBOT_MXWO_OS xmlns="http://www.ibm.com/maximo" baseLanguage="..." transLanguage="..." ...>
      <PBOT_MXWO_OSQuery>
        ...
      </PBOT_MXWO_OSQuery>
    </QueryPBOT_MXWO_OS>
  </s:Body>
</s:Envelope>

The problem is that WCF recognized QueryPBOT_MXWO_OS as wrapper element for request. I'm not sure why it fires exception but probably there is some restriction that wrapper element can't have attributes. I'm suspicious that this is just global error handling shared with version which uses IsWrapped=false where usage of attributes is error.

You can try to modify your proxy in this way:

[System.Diagnostics.DebuggerStepThroughAttribute()]        
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]        
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]        
public partial class QueryPBOT_MXWO_OSRequest 
{ 
    [MessageBodyMemberAttribute(Name="QueryPBOT_MXWO_OS", Namespace="http://www.ibm.com/maximo")]
    public QueryPBOT_MXWO_OS QueryPBOT_MXWO_OS { get; set; }
}  

[XmlRoot(ElementName="QueryPBOT_MXWO_OS", Namespace="http://www.ibm.com/maximo")]
public class QueryPBOT_MXWO_OS
{
    [XmlElement(Namespace="http://www.ibm.com/maximo")]    
    public ConsoleApplication7.wsMaximo.PBOT_MXWO_OSQueryType PBOT_MXWO_OSQuery;           

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]           
    public string baseLanguage;           

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]         
    public string transLanguage;           

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]       
    public string messageID;           

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]       
    public string maximoVersion;           

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]       
    [System.ComponentModel.DefaultValueAttribute(false)]           
    public bool uniqueResult;           

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]      
    public string maxItems;           

    [XmlAttribute(Namespace="http://www.ibm.com/maximo")]           
    [System.ComponentModel.DefaultValueAttribute("0")]           
    public string rsStart;  
}     
Ladislav Mrnka
Laislav, thanks for your comment, but what I'm really looking for is a solution where I don't have to touch the proxy class file at all to get the web service working. If I comment out all instances of [XmlAttribute()] from the proxy class file, the web service will work.
John K.
But in that case all those parameters are transported as elements. So do you need those parameters? If not simply remove them from WSDL and regenerate the proxy.
Ladislav Mrnka