none
svcutil generates ReplyAction="*"

    Question

  • Hi,

     

    I have tried to generate a service proxy from a wsdl file using svcutil, and that worked fine, but when I deployed that service, it did not contain any method.

     

    I was finally able to find the problem. It comes from the fact that svcutil generates code with the attribute ReplyAction="*" for the OperationContractAttribute decoration.

    I don't know why, but this "*" value keeps WCF to correctly expose the method. If I change it to any other value, all works fine.

     

    Code Snippet

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]

    [System.ServiceModel.ServiceContractAttribute(Namespace="my.namespace", ConfigurationName="MyService")]

    public interface MyService

    {

        // CODEGEN: Generating message contract since the operation subscriptionOperation is neither RPC nor document wrapped.

        [System.ServiceModel.OperationContractAttribute(Action="subscriptionOperation", ReplyAction="*")]

        [System.ServiceModel.FaultContractAttribute(typeof(object), Action="subscriptionOperation", Name="subscriptionFault", Namespace="my.namespace")]

        [System.ServiceModel.XmlSerializerFormatAttribute()]

        subscribeResponse subscriptionOperation(subscribeRequest request);

    }

     

    I have two questions :

    - why does this "*" attribute poses a problem?

    - is there a possibility to tell svcutil not to generate it?

     

    Thank you.

    Friday, August 01, 2008 12:29 PM

Answers

  •  

    Hi REY Joël,

     

    1)

    Here's a link that may answer your question why the asterisk poses a "problem".

     

    http://sergeyshishkin.spaces.live.com/Blog/cns!9F19E53BA9C1D63F!188.entry

     

     

    2) remove the soap action

     

    <soapSurpriseperation soapAction="urnTongue TiedubscriptionOperation" style="document" />

     

    This will force svcutil to use the default action and replyAction values when generating the operation contract.  FYI, according to soap1.1 Note, the soap action is required if you are using http transport (Section 3.4), which you are using from looking at the posted wsdl.  However, soap 1.1 was never a recommendation but AFAIK, is widely used.  Soap1.2 Recommendation superseded 1.1 and does not require the soapAction.  So, who does this affect the code gen, not much.  Just, fyi.

     

    Also, the reason why you are getting "// CODEGEN: Generating message ..." message is because your declaration does not follow either the document/literal or document/literal wrapped pattern.

     

    Here is a nice link to show the difference

    http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/

     

    Wcf uses document/literal wrapped and it looks like, from the wsdl, that is what you are striving for.   

    subscriptionResponse should contain an element of notificiationType instead of being defined as of that type. I.e., subscriptionResponse is a wrapper element and should contain child elements.

     

    The other thing is the message part name should be "parameters".

     

    Here are links for writing a wcf compliant wsdl.

    http://kjellsj.blogspot.com/2008/03/wcf-datacontractserializer-schema-rules.html

    http://msdn.microsoft.com/en-us/library/ms733112.aspx

     

    Another thing is that your message should be in the same namespace as your port type.  It is not require but wcf will your subscription and subscriptionResponse as message contracts, if you don't.

     

    However, if your operation has more than one return value, svcutil generates some ugly code, IMO.  For example, if you are returning an int and string, the service contract will look like this.

     

    Code Snippet

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]

    [System.ServiceModel.ServiceContractAttribute(Namespace="urn:definitions", ConfigurationName="PortType_Subscription")]

    public interface PortType_Subscription

    {

    [System.ServiceModel.OperationContractAttribute(Action="urn:definitions:PortType_Subscription:subscriptionRequest", ReplyAction="urn:definitions:PortType_Subscription:subscriptionResponse")]

    [System.ServiceModel.FaultContractAttribute(typeof(namespace2.subscriptionFault), Action="http://www.w3.org/2005/08/addressing/soap/fault", Name="subscriptionFault", Namespace="urn:namespace2")]

    [return: System.ServiceModel.MessageParameterAttribute(Name="name")]

    string subscription([System.ServiceModel.MessageParameterAttribute(Name="subscription")] string subscription1, ref string query);

    }

     

     

    Every variable after the first gets append to the method signature with the ref keyword.  Ugly.  The "workaround" is to define a type that contains all your return variables.  This way remove the ref parameters.  They are all part of the return type.  However, the drawback is that you create a type for no other reason than to contain the return values.

     

     

    Long winded reply but HTH,

    An

     

     

     

     

     

    Monday, August 11, 2008 8:14 AM

All replies

  • Hello,

     

     

    Could you post the wsdl file?

     

    thanks,

    An

     

    Saturday, August 02, 2008 10:05 AM
  • Sure I can An. The wsdl is divided into three parts: one wsdl containing the service and the binding, one wsdl for the portType and the messages, end one xsd for the types.

     

    First WSDL :

    Code Snippet

    <?xml version="1.0" encoding="UTF-8" ?>
    <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="urn:subscriptionservice" xmlns:def="urn:definitions" targetNamespace="urn:subscriptionservice">
      <wsdl:import namespace="urn:definitions" location="Test_Def.wsdl" />
      <wsdl:binding name="Binding_Subscription" type="def:PortType_Subscription">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="subscriptionOperation">
          <soap:operation soapAction="urn:subscriptionOperation" style="document" />
          <wsdl:input name="subscribeRequest">
            <soap:body use="literal" />
          </wsdl:input>
          <wsdl:output name="subscribeResponse">
            <soap:body use="literal" />
          </wsdl:output>
          <wsdl:fault name="subscribeFault">
            <soap:fault name="subscribeFault" use="literal" />
          </wsdl:fault>
        </wsdl:operation>
      </wsdl:binding>
      <wsdl:service name="Service_Subscription">
        <wsdl:port name="Port_Subscription" binding="tns:Binding_Subscription">
          <soap:address location="http://localhost/TestSubscription" />
        </wsdl:port>
      </wsdl:service>
    </wsdl:definitions>

     

    second WSDL:

    Code Snippet
    <?xml version="1.0" encoding="UTF-8" ?>
    <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:ns="urn:definitions" xmlns:ns1="urn:namespace1" xmlns:ns2="urn:namespace2" targetNamespace="urn:definitions">
      <wsdl:types>
        <xs:schema>
          <xs:import namespace="urn:namespace2" schemaLocation="Test_Types.xsd" />
        </xs:schema>
      </wsdl:types>
      <wsdl:message name="subRequestMessage">
        <wsdl:part name="request" element="ns2:subscriptionRequest" />
      </wsdl:message>
      <wsdl:message name="subResponseMessage">
        <wsdl:part name="response" element="ns2:subscriptionResponse" />
      </wsdl:message>
      <wsdl:message name="subscriptionFaultMessage">
        <wsdl:part name="fault" element="ns2:subscriptionFault" />
      </wsdl:message>
      <wsdl:portType name="PortType_Subscription">
        <wsdl:operation name="subscriptionOperation">
          <wsdl:input name="subscribeRequest" message="ns:subRequestMessage" />
          <wsdl:output name="subscribeResponse" message="ns:subResponseMessage" />
          <wsdl:fault name="subscribeFault" message="ns:subscriptionFaultMessage" />
        </wsdl:operation>
      </wsdl:portType>
    </wsdl:definitions>
     
    xsd :
     
    Code Snippet
    <?xml version="1.0" encoding="UTF-8" ?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:nffi="urn:namespace1" xmlns="urn:namespace2" targetNamespace="urn:namespace2" elementFormDefault="qualified" attributeFormDefault="unqualified">
      <xs:simpleType name="subscriptionType">
        <xs:restriction base="xs:string" />
      </xs:simpleType>
      <xs:simpleType name="queryType">
        <xs:restriction base="xs:string" />
      </xs:simpleType>
      <xs:simpleType name="notificationType">
        <xs:restriction base="xs:string" />
      </xs:simpleType>
      <xs:element name="subscriptionRequest">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="subscription" type="subscriptionType" />
            <xs:element name="query" type="queryType" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="subscriptionResponse" type="notificationType" />
      <xs:element name="subscriptionFault" />
    </xs:schema>

     

     

    Monday, August 04, 2008 9:56 AM
  •  

    Hi REY Joël,

     

    1)

    Here's a link that may answer your question why the asterisk poses a "problem".

     

    http://sergeyshishkin.spaces.live.com/Blog/cns!9F19E53BA9C1D63F!188.entry

     

     

    2) remove the soap action

     

    <soapSurpriseperation soapAction="urnTongue TiedubscriptionOperation" style="document" />

     

    This will force svcutil to use the default action and replyAction values when generating the operation contract.  FYI, according to soap1.1 Note, the soap action is required if you are using http transport (Section 3.4), which you are using from looking at the posted wsdl.  However, soap 1.1 was never a recommendation but AFAIK, is widely used.  Soap1.2 Recommendation superseded 1.1 and does not require the soapAction.  So, who does this affect the code gen, not much.  Just, fyi.

     

    Also, the reason why you are getting "// CODEGEN: Generating message ..." message is because your declaration does not follow either the document/literal or document/literal wrapped pattern.

     

    Here is a nice link to show the difference

    http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/

     

    Wcf uses document/literal wrapped and it looks like, from the wsdl, that is what you are striving for.   

    subscriptionResponse should contain an element of notificiationType instead of being defined as of that type. I.e., subscriptionResponse is a wrapper element and should contain child elements.

     

    The other thing is the message part name should be "parameters".

     

    Here are links for writing a wcf compliant wsdl.

    http://kjellsj.blogspot.com/2008/03/wcf-datacontractserializer-schema-rules.html

    http://msdn.microsoft.com/en-us/library/ms733112.aspx

     

    Another thing is that your message should be in the same namespace as your port type.  It is not require but wcf will your subscription and subscriptionResponse as message contracts, if you don't.

     

    However, if your operation has more than one return value, svcutil generates some ugly code, IMO.  For example, if you are returning an int and string, the service contract will look like this.

     

    Code Snippet

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]

    [System.ServiceModel.ServiceContractAttribute(Namespace="urn:definitions", ConfigurationName="PortType_Subscription")]

    public interface PortType_Subscription

    {

    [System.ServiceModel.OperationContractAttribute(Action="urn:definitions:PortType_Subscription:subscriptionRequest", ReplyAction="urn:definitions:PortType_Subscription:subscriptionResponse")]

    [System.ServiceModel.FaultContractAttribute(typeof(namespace2.subscriptionFault), Action="http://www.w3.org/2005/08/addressing/soap/fault", Name="subscriptionFault", Namespace="urn:namespace2")]

    [return: System.ServiceModel.MessageParameterAttribute(Name="name")]

    string subscription([System.ServiceModel.MessageParameterAttribute(Name="subscription")] string subscription1, ref string query);

    }

     

     

    Every variable after the first gets append to the method signature with the ref keyword.  Ugly.  The "workaround" is to define a type that contains all your return variables.  This way remove the ref parameters.  They are all part of the return type.  However, the drawback is that you create a type for no other reason than to contain the return values.

     

     

    Long winded reply but HTH,

    An

     

     

     

     

     

    Monday, August 11, 2008 8:14 AM
  • Just in case you need the updated wsdl files.

     

    Code Snippet

    <?xml version="1.0" encoding="UTF-8" ?>

    <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

    xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"

    xmlns:xs="http://www.w3.org/2001/XMLSchema"

    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"

    xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"

    xmlns:tns="urn:subscriptionservice"

    xmlns:def="urn:definitions"

    targetNamespace="urn:subscriptionservice">

    <wsdl:import namespace="urn:definitions" location="Test_Def.wsdl" />

    <wsdl:binding name="Binding_Subscription" type="def:PortType_Subscription">

    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />

    <wsdl:operation name="subscription">

    <soap:operation soapAction="urn:subscriptionOperation" style="document" />

    <wsdl:input >

    <soap:body use="literal" />

    </< FONT>wsdl:input>

    <wsdl:output>

    <soap:body use="literal" />

    </< FONT>wsdl:output>

    <wsdl:fault name="subscribeFault">

    <soap:fault name="subscribeFault" use="literal" />

    </< FONT>wsdl:fault>

    </< FONT>wsdl:operation>

    </< FONT>wsdl:binding>

    <wsdl:service name="Service_Subscription">

    <wsdl:port name="Port_Subscription" binding="tns:Binding_Subscription">

    <soap:address location="http://localhost/TestSubscription" />

    </< FONT>wsdl:port>

    </< FONT>wsdl:service>

    </< FONT>wsdl:definitions>

     

     

     

    Code Snippet

    <?xml version="1.0" encoding="UTF-8" ?>

    <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

    xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"

    xmlns:xs="http://www.w3.org/2001/XMLSchema"

    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"

    xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"

    xmlns:ns="urn:definitions"

    xmlns:ns1="urn:namespace1"

    xmlns:ns2="urn:namespace2"

    targetNamespace="urn:definitions"

    xmlns="urn:definitions"

    >

    <wsdl:types>

    <xs:schema targetNamespace="urn:definitions" xmlns:ns2="urn:namespace2" elementFormDefault="qualified">

    <xs:import namespace="urn:namespace2" schemaLocation="Test_Types.xsd" />

    <xs:element name="subscription">

    <xs:complexType>

    <xs:sequence>

    <xs:element name="subscription" type="ns2:subscriptionType" />

    <xs:element name="query" type="ns2:queryType" />

    </< FONT>xs:sequence>

    </< FONT>xs:complexType>

    </< FONT>xs:element>

    <xs:element name="subscriptionResponse" >

    <xs:complexType>

    <xs:sequence>

    <xs:element name="name"

    type="xs:string" nillable="true"/>

    <xs:element name="query"

    type="ns2:queryType" nillable="true"/>

    </< FONT>xs:sequence>

    </< FONT>xs:complexType>

    </< FONT>xs:element>

    </< FONT>xs:schema>

    </< FONT>wsdl:types>

    <wsdl:message name="subRequestMessage">

    <wsdl:part name="parameters" element="subscription" />

    </< FONT>wsdl:message>

    <wsdl:message name="subResponseMessage">

    <wsdl:part name="parameters" element="subscriptionResponse" />

    </< FONT>wsdl:message>

    <wsdl:message name="subscriptionFaultMessage">

    <wsdl:part name="fault" element="ns2:subscriptionFault" />

    </< FONT>wsdl:message>

    <wsdl:portType name="PortType_Subscription">

    <wsdl:operation name="subscription">

    <wsdl:input message="ns:subRequestMessage" />

    <wsdl:output message="ns:subResponseMessage" />

    <wsdl:fault name="subscribeFault" message="ns:subscriptionFaultMessage" />

    </< FONT>wsdl:operation>

    </< FONT>wsdl:portType>

    </< FONT>wsdl:definitions>

     

     

    Code Snippet

     

    <?xml version="1.0" encoding="UTF-8" ?>

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

    xmlns="urn:namespace2"

    targetNamespace="urn:namespace2"

    elementFormDefault="qualified"

    attributeFormDefault="unqualified">

    <!--xmlns:nffi="urn:namespace1"-->

    <xs:simpleType name="subscriptionType">

    <xs:restriction base="xs:string" />

    </xs:simpleType>

    <xs:simpleType name="queryType">

    <xs:restriction base="xs:string" />

    </xs:simpleType>

    <xs:simpleType name="notificationType">

    <xs:restriction base="xs:string" />

    </xs:simpleType>

    <xs:element name="subscriptionFault" />

     

    </xs:schema>

     

     

     

    Monday, August 11, 2008 8:21 AM
  • Hi An Phu,

     

    Sorry for that late answer too, I wasn't here this last week.

     

    I just want to thank you a lot for your answer. The link is exactly the explaination I was looking for. Now I know why I couldn't see my methods published... Still, it seems a bit strange that the metadata publisher acs this way.

     

    As for the rest of your explanations, I thank you again, they are truly helpful. But unfortunatly, I can't change my WSDL.

    I didn't know there was a WCF compliant way of writting WSDLs, I though WCF would follow the WSDL specification in its every aspects. Thanks for pointing that out.

     

    If I can push a litle and ask about something else, I encountered another problem with my WSDL. When the same XML complex type is used in a Fault element and as an element in a body part, the svcutil.exe tool generates the code for that type twice, but in two different ways. One as an extension of IXmlSerializable, and the other with the SerializableAttribute() and XmlTypeAttribute(namespace). Here is an example taken from the generated code :

     

    Code Snippet

    [System.CodeDomCompiler.GeneratedCodeAttribute("svcutil", "....")]

    [System.SerializableAttribute()]

    [System.DiagnosticsCode.DebuggerStepThroughAttribute()]

    [System.ComponentModel.DesignerCategoryAttribute("code")]

    [System.Xml.Serialization.XmlTypeAttribute(Namespace="my.namespace")]

    public partial class MyClass

    { ... }

     

    .....

    namespace my.namespace

    {

    [System.Diagnostics.DebuggerStepThroughAttribute()]

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "...")]

    [System.Xml.Serialization.XmlSchemaProviderAttribute("ExportSchema")]

    [System.Xml.Serialization.XmlRootAttribute(ElementName="...", Namespace="my.namespace", IsNullable=false)]

    public partial class MyClass : object, System.Runtime.Serialization.IXmlSerializable

    { ... }

     

    ...

     

    }

     

     

    Due to this duplicate class definition, I can't compile. I had to remove the Fault element to generate correct code. Do you have a clue what could be the problem? Unfortunatly, I can't show you my WSDL. But maybe this is something you know about.

     

    Either way, thank you for your help, it is really appreciated.

    • Proposed as answer by osttocs Sunday, March 01, 2009 2:30 PM
    Tuesday, August 19, 2008 12:13 PM
  • Oh and by the way, I'm using the "/serializer:XmlSerializer" option for svcutil. My WSDL contains types that DataContractSerializer cannot serialize.

     

    Wednesday, August 20, 2008 9:09 AM
  • In .NET 3.0, the Fault has to be completely DataContractSerializer compliant.  If you share types between your regular contract and any fault contracts, then you would need to effectively unshare those and make them DataContractSerializer compliant.  In .NET 3.5 (possibly .NET 3.0 SP1, but I'm not sure), Microsoft added support for non-DataContractSerializer compliant faults.  So the other options is to upgrade to a WCF version that supports XmlSerializer in the faults.
    • Proposed as answer by osttocs Sunday, March 01, 2009 2:33 PM
    Sunday, March 01, 2009 2:33 PM
  • So is there a svcutil.exe for .NET 3.5 that correctly generates XmlSerializer code for Faults?
    I'm currently using C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin\svcutil.exe

    This version generates code with the attribute:
       [System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "3.0.4506.648")]
    So ... I assume its only for .NET 3.0


    Wednesday, November 18, 2009 2:19 AM