WCF:WSDL优先方法:生成错误类型的问题

时间:2010-03-16 14:22:48

标签: c# .net wsdl wcf

我目前正在创建一个与WS-I Basic Profile 1.1兼容的WCF Web服务。我正在使用wsdl-first方法(实际上是第一次),首先定义复杂类型的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不会生成这些属性? 网上的一些消息来源建议添加svcutil的 / useSerializerForFaults 选项。我试了一下,它没有给我一个例外,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 个答案:

答案 0 :(得分:2)

我可以通过svcutil(使用/ 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行语句(请注意,我正在为给定的现有服务生成服务引用 - 但它在代码生成方面应该没有太大区别):

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

答案 1 :(得分:2)

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