代码之家  ›  专栏  ›  技术社区  ›  Juri

wcf:wsdl优先方法:生成错误类型的问题

  •  4
  • Juri  · 技术社区  · 15 年前

    我目前正在创建一个应该与ws-ibasicprofile1.1兼容的wcf webservice。我使用的是wsdl优先方法(实际上是第一次),首先为复杂类型定义xsd、wsdl,然后使用svcutil.exe生成相应的服务器以及客户端接口/代理。到目前为止一切正常。然后我决定 添加故障 到我的WSDL。

    使用svcutil重新生成成功,但随后我注意到生成的错误没有我在xsd文件(由wsdl导入)中定义的属性。

    复杂数据类型xsd

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:tns="http://myprod.services.mycompany.com/groups_v1.xsd"
        targetNamespace="http://myprod.services.mycompany.com/groupsfault_v1.xsd">
    
        <xsd:complexType name="groupsFault">
            <xsd:sequence>
                <xsd:element name="code" type="xsd:int"/>
                <xsd:element name="message" type="xsd:string"/>
            </xsd:sequence>
        </xsd:complexType>
    
    </xsd:schema>
    

    故障XSD定义

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:tns="http://myprod.services.mycompany.com/groups_v1.xsd"
        targetNamespace="http://myprod.services.mycompany.com/groups_v1.xsd">
    
        <xsd:complexType name="group">
            <xsd:sequence>
                <xsd:element name="groupDescD" type="xsd:string" />
                <xsd:element name="groupDescI" type="xsd:string" />
                <xsd:element name="groupProtNr" type="xsd:string" />
            </xsd:sequence>
        </xsd:complexType>
    
    </xsd:schema>
    

    使用上述两个xsd的wsdl

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <wsdl:definitions name="Groups_v1.wsdl"
        targetNamespace="http://myprod.services.mycompany.com/groups_v1.wsdl"
        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
        xmlns:tns="http://myprod.services.mycompany.com/groups_v1.wsdl"
        xmlns:fault="http://myprod.services.mycompany.com/groupsfault_v1.xsd"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <wsdl:types>
            <xsd:schema targetNamespace="http://myprod.services.mycompany.com/groups_v1.wsdl"
                    xmlns="http://www.w3.org/2001/XMLSchema"
                    xmlns:groups="http://myprod.services.mycompany.com/groups_v1.xsd">
    
                <import namespace="http://myprod.services.mycompany.com/groups_v1.xsd" schemaLocation="./Groups.xsd"/>
                <import namespace="http://myprod.services.mycompany.com/groupsfault_v1.xsd" schemaLocation="./GroupsFault.xsd"/>
    
                <xsd:element name="getGroupList">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="StationProtNr" type="xsd:string" />
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
                <xsd:element name="getGroupListResponse">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element maxOccurs="unbounded" name="group" type="groups:group" />
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
    
                <xsd:element name="groupsFault">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="groupsFault" type="fault:groupsFault"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
    
            </xsd:schema>
        </wsdl:types>
        <wsdl:message name="getGroupList">
            <wsdl:part element="tns:getGroupList" name="parameters" />
        </wsdl:message>
        <wsdl:message name="getGroupListResponse">
            <wsdl:part element="tns:getGroupListResponse" name="parameters" />
        </wsdl:message>
    
        <wsdl:message name="groupsFault">
            <wsdl:part name="parameters" element="tns:groupsFault" />
        </wsdl:message>
    
        <wsdl:portType name="Groups_v1">
            <wsdl:operation name="getGroupList">
                <wsdl:input name="getGroupList" message="tns:getGroupList"/>
                <wsdl:output name="getGroupListResponse" message="tns:getGroupListResponse"/>
                <wsdl:fault name="getGroupListFault" message="tns:groupsFault" />
            </wsdl:operation>
        </wsdl:portType>
    
        <wsdl:binding name="Groups_v1_SOAPBinding" type="tns:Groups_v1">
            <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
            <wsdl:operation name="getGroupList">
                <soap:operation soapAction="http://myprod.services.mycompany.com/groups_v1/getGroupList" />
                <wsdl:input name="getGroupList">
                    <soap:body use="literal" />
                </wsdl:input>
                <wsdl:output name="getGroupListResponse">
                    <soap:body use="literal" />
                </wsdl:output>
                <wsdl:fault name="getGroupListFault">
                    <soap:fault name="getGroupListFault" use="literal"/>
                </wsdl:fault>
            </wsdl:operation>
        </wsdl:binding>
    
    
        <wsdl:service name="getGroupList">
            <wsdl:port binding="tns:Groups_v1_SOAPBinding" name="GroupsSOAP">
                <soap:address location="http://myprod.services.mycompany.com/groups_v1" />
            </wsdl:port>
        </wsdl:service>
    </wsdl:definitions>
    

    生成的.NET错误对象

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
    [System.Xml.Serialization.XmlSchemaProviderAttribute("ExportSchema")]
    [System.Xml.Serialization.XmlRootAttribute(IsNullable=false)]
    public partial class groupFault : object, System.Xml.Serialization.IXmlSerializable
    {
    
        private System.Xml.XmlNode[] nodesField;
    
        private static System.Xml.XmlQualifiedName typeName = new System.Xml.XmlQualifiedName("groupFault", "http://sicp.services.siag.it/groups_v1.wsdl");
    
        public System.Xml.XmlNode[] Nodes
        {
            get
            {
                return this.nodesField;
            }
            set
            {
                this.nodesField = value;
            }
        }
    
        public void ReadXml(System.Xml.XmlReader reader)
        {
            this.nodesField = System.Runtime.Serialization.XmlSerializableServices.ReadNodes(reader);
        }
    
        public void WriteXml(System.Xml.XmlWriter writer)
        {
            System.Runtime.Serialization.XmlSerializableServices.WriteNodes(writer, this.Nodes);
        }
    
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }
    
        public static System.Xml.XmlQualifiedName ExportSchema(System.Xml.Schema.XmlSchemaSet schemas)
        {
            System.Runtime.Serialization.XmlSerializableServices.AddDefaultSchema(schemas, typeName);
            return typeName;
        }
    }
    

    这样行吗??我希望创建一个包含“code”和“message”s.t.属性的对象,然后可以使用

    ...
    throw new FaultException<groupFault>(new groupFault { code=100, message="error" });
    ...
    

    (很抱歉使用小写类型定义,但这是从wsdl生成的代码)

    为什么svcutil.exe不生成这些属性?? 网络上的一些资源建议添加 /使用SerializerForFaults svcutil的选项。我试过了,但如果在 wsdl:portType 宣言。不过,其他一些工具的验证也成功了。

    我的命令行输出(也许这有助于某人识别任何问题):

    C:\>svcutil /out:IGroupsServi
    ce.cs /n:*,MyCompany.MyProduct.MyModule /UseSerializerForFaults *.wsdl *.xsd
    Microsoft (R) Service Model Metadata Tool
    [Microsoft (R) Windows (R) Communication Foundation, Version 3.0.4506.2152]
    Copyright (c) Microsoft Corporation.  All rights reserved.
    
    Error: Cannot import wsdl:portType
    Detail: An exception was thrown while running a WSDL import extension: System.Se
    rviceModel.Description.XmlSerializerMessageContractImporter
    Error: The datatype 'http://myprod.services.mycompany.com/groups_v1.wsdl:groupsFault' is
     missing.
    XPath to Error Source: //wsdl:definitions[@targetNamespace='http://myprod.services.mycompany.com/groups_v1.wsdl']/wsdl:portType[@name='Groups_v1']
    
    
    Error: Cannot import wsdl:binding
    Detail: There was an error importing a wsdl:portType that the wsdl:binding is de
    pendent on.
    XPath to wsdl:portType: //wsdl:definitions[@targetNamespace='http://myprod.services.mycompany.com/groups_v1.wsdl']/wsdl:portType[@name='Groups_v1']
    XPath to Error Source: //wsdl:definitions[@targetNamespace='http://myprod.services.mycompany.com/groups_v1.wsdl']/wsdl:binding[@name='Groups_v1_SOAPBinding']
    
    
    Error: Cannot import wsdl:port
    Detail: There was an error importing a wsdl:binding that the wsdl:port is depend
    ent on.
    XPath to wsdl:binding: //wsdl:definitions[@targetNamespace='http://myprod.services.mycompany.com/groups_v1.wsdl']/wsdl:binding[@name='Groups_v1_SOAPBinding']
    XPath to Error Source: //wsdl:definitions[@targetNamespace='http://myprod.services.mycompany.com/groups_v1.wsdl']/wsdl:service[@name='getGroupList']/wsdl:port[@name='Gr
    oupsSOAP']
    
    
    Generating files...
    Warning: No code was generated.
    If you were trying to generate a client, this could be because the metadata docu
    ments did not contain any valid contracts or services
    or because all contracts/services were discovered to exist in /reference assembl
    ies. Verify that you passed all the metadata documents to the tool.
    
    Warning: If you would like to generate data contracts from schemas make sure to
    use the /dataContractOnly option.
    
    C:\>
    

    任何帮助都是 非常 感谢:)THX

    2 回复  |  直到 15 年前
        1
  •  2
  •   David    15 年前

    我认为您的问题是需要将elementformdefault=“qualified”作为属性添加到wsdl的xsd:schema部分。这对我很有用。

        2
  •  2
  •   JohnIdol    15 年前

    我可以给您一个通过svcutil(with/useSerializerForFaults)为我正确生成的错误示例:

    <xsd:schema targetNamespace="http://myproduct.mycompany.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:complexType name="MyError">
        <xsd:sequence>
          <!-- other stuff -->
          <xsd:element name="description" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
    </xsd:schema>
    

    是否可能只是缺少类型的命名空间?

    这是生成的代码:

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "3.0.4506.2152")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://myproduct.mycompany.com/")]
    public partial class MyError
    {
    
      // other stuff
    
      private string descriptionField;
    
      /// <remarks/>
      [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 1)]
      public string description
      {
        get
        {
          return this.descriptionField;
        }
        set
        {
          this.descriptionField = value;
        }
      }
    }
    

    这是我的完整svcutil cmd line语句(请注意,我正在为给定的现有服务生成一个服务引用,但在代码生成方面不应该有太大的区别):

    svcutil /t:code /out:C:\MyRepository\GeneratedCode\MyServiceReference.cs /n:*,myproduct.mycompany.servicereference /UseSerializerForFaults C:\MyRepository\*.wsdl C:\MyRepository\*.xsd /config:C:\MyRepository\GeneratedCode\MyServiceReference.config