tags:

views:

1177

answers:

2

I'm generating client side web service code using svcutil. The wsdl contract I'm using contains a soap fault. When the code is generated the fault seems to be wrapped in the namespace it was defined in the contract.

Can anyone explain why?

I'm simply running svcutil [filename]

Example WSDL:

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://tempuri.org/"&gt;
<wsdl:types>
 <s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/"&gt;
  <s:element name="HelloFault">
   <s:complexType/>
  </s:element>
  <s:element name="HelloWorld">
   <s:complexType/>
  </s:element>
  <s:element name="HelloWorldResponse">
   <s:complexType>
    <s:sequence>
     <s:element minOccurs="0" maxOccurs="1" name="HelloWorldResult" type="s:string"/>
    </s:sequence>
   </s:complexType>
  </s:element>
 </s:schema>
</wsdl:types>
<wsdl:message name="HelloWorldSoapIn">
 <wsdl:part name="parameters" element="tns:HelloWorld"/>
</wsdl:message>
<wsdl:message name="HelloWorldSoapOut">
 <wsdl:part name="parameters" element="tns:HelloWorldResponse"/>
</wsdl:message>
<wsdl:message name="NewMessage">
 <wsdl:part name="detail" element="tns:HelloFault"/>
</wsdl:message>
<wsdl:portType name="Service1Soap">
 <wsdl:operation name="HelloWorld">
  <wsdl:input message="tns:HelloWorldSoapIn"/>
  <wsdl:output message="tns:HelloWorldSoapOut"/>
  <wsdl:fault name="FaultName" message="tns:NewMessage"/>
 </wsdl:operation>
</wsdl:portType>
<wsdl:binding name="Service1Soap12" type="tns:Service1Soap">
 <soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/&gt;
 <wsdl:operation name="HelloWorld">
  <soap12:operation soapAction="http://tempuri.org/HelloWorld" soapActionRequired="" style="document"/>
  <wsdl:input>
   <soap12:body use="literal"/>
  </wsdl:input>
  <wsdl:output>
   <soap12:body use="literal"/>
  </wsdl:output>
  <wsdl:fault name="FaultName">
   <soap12:fault name="FaultName" use="literal"/>
  </wsdl:fault>
 </wsdl:operation>
</wsdl:binding>

Generates:

namespace tempuri.org
{

using System.Runtime.Serialization;



[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="HelloFault", Namespace="http://tempuri.org/")]
public partial class HelloFault : object, System.Runtime.Serialization.IExtensibleDataObject
{

    private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

    public System.Runtime.Serialization.ExtensionDataObject ExtensionData
    {
        get
        {
            return this.extensionDataField;
        }
        set
        {
            this.extensionDataField = value;
        }
    }
}

}

But other types declared in the contract are declared without a namespace?

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class HelloWorldRequest
{
...
A: 

I'm not sure I understand what the problem is... can you clarify?

From the looks of it, it would seem WCF is doing the right thing... the generated class has the right namespace URI in the [DataContract] attribute according to the schema in the WSDL fragment you showed.

What were you expecting?

Update: OK, I see what you're saying, but in this specific case, it's not unexpected either. If you look closely, notice that the other class you mention (HelloWorldRequest) is a Message Contract, not a DataContract. Message Contracts don't have namespaces themselves, though they can specify a namespace for the wrapper element around the message body (see the WrapperNamespace property).

In your case, the message contract specifies that it is not wrapped, so the WrapperNamespace wouldn't apply anyway.

Update #2: Regarding the CLR namespace (and not the XML namespace URI), SvcUtil does give you a way to control that; check out the /namespace: argument in the documentation.

tomasr
Sorry, my point was none of the other types are in the namespace they were declared in. Only the soap fault. I'll edit the post. Thanks
I now realise that I haven't been clear, I was referring to the C# namespace and not the namespace defined in the DataContract.
Many thanks, I did know about the namespace switch. (I've not helped by wording my question badly!) Do you know why the default behaviour is to put the faults in a CLR namespace and not messages? Seems odd? in particular when you get faults in namespaces like 'http://www.domain/name/2009/03/18' etc
I do not know the reason it happens, but not surprised by it, svcutil has a lot of bugs :)Other than that, there are a lot of things that influence where code gets generated by svcutil based on how it interprets the contract...
tomasr
A: 

You have to use the /UseSerializerForFaults attribute on svcutil, this will cause the XmlSerializer to be used for reading and writing faults (but only those), instead of the default DataContractSerializer (which will still be used for the rest of the stuff).

This seems to be a genuine bug - more info on my blog post.

JohnIdol
what if /UseSerializerForFaults is signaled as a not recognized option??
Juri