序列化.NET WCF服务类型的问题:服务WSDL在XSD中定义空类型

时间:2011-06-06 20:32:24

标签: c# .net wcf web-services serialization

我正在使用WCF编写Web服务。

  1. 我创建了数据合同。

  2. 我创建了服务合同(界面)。我定义了方法(其参数的类型与数据契约类型相同)。

  3. 我实现了创建服务类的服务合同。

  4. 我使用svc文件和IIS托管我的服务。

  5. 我尝试了我的服务,寻找http://localhost/myvirtdiriis/myservice.svc - >该服务已加载,并且显示了描述我的服务存在的漂亮网页。

  6. 我想看一下WSDL。使用提供的链接我可以看到只定义了类型,我只能看到类型定义(如<complexType>),但内部没有(类型为空)。

  7. 我编写了一个简单的客户端,对操作的调用很顺利,但是当返回类型时它是空的(内部字段具有构造值,而我的服务在那里放置了一些值),例如,一个调用返回具有由操作契约方法设置的三个字符串的类型为“Hello”,“Hello2”和“Hello3”的操作,返回将这些字符串设置为""的类型(构造值,就好像没有发生更改一样) )。

  8. 发生了什么事?

    序列化似乎失败了。

    我提供一些:

    A1)服务合同的一部分:

    [ServiceContract(Namespace = "http://opcfoundation.org/webservices/XMLDA/1.0/")]
       public interface IOCXSService {
          [OperationContract(Action = "http://opcfoundation.org/webservices/XMLDA/1.0/Browse")]
          BrowseResponse Browse(BrowseRequest request);
          ...
    }
    

    A2)服务实施:

    public class MyService : IOCXSService {
          ...
          public BrowseResponse Browse(BrowseRequest request) {
             ...
          }
          ...
       }
    

    B)类型:

    [DataContract(Namespace = "http://opcfoundation.org/webservices/XMLDA/1.0/", Name = "BrowseResponse")]
        [System.ServiceModel.MessageContractAttribute(WrapperName = "BrowseResponse", WrapperNamespace = "http://opcfoundation.org/webservices/XMLDA/1.0/", IsWrapped = true)]
        public class BrowseResponse {
    
            [DataMember(Name = "BrowseResult", Order = 0)]
            public OCXS.OCXSServiceLibrary.OPCXMLDA10.ReplyBase BrowseResult;
    
            [DataMember(Name = "Elements", Order = 1)]
            public BrowseElement[] Elements;
    
            [DataMember(Name = "Errors", Order = 2)]
            public OPCError[] Errors;
    
            [DataMember(Name = "ContinuationPoint", Order = 3)]
            public string ContinuationPoint;
    
            [DataMember(Name = "MoreElements", Order = 4)]
            public bool MoreElements;
    
            public BrowseResponse() {
            }
    
            public BrowseResponse(OCXS.OCXSServiceLibrary.OPCXMLDA10.ReplyBase BrowseResult, BrowseElement[] Elements, OPCError[] Errors, string ContinuationPoint, bool MoreElements) {
                this.BrowseResult = BrowseResult;
                this.Elements = Elements;
                this.Errors = Errors;
                this.ContinuationPoint = ContinuationPoint;
                this.MoreElements = MoreElements;
            }
    
    [DataContract(Namespace = "http://opcfoundation.org/webservices/XMLDA/1.0/", Name = "ReplyBase")]
        public class ReplyBase : System.ComponentModel.INotifyPropertyChanged {
    
            private System.DateTime rcvTimeField;
    
            private System.DateTime replyTimeField;
    
            private string clientRequestHandleField;
    
            private string revisedLocaleIDField;
    
            private serverState serverStateField;
    
            [DataMember(Name = "RcvTime", Order = 0)]
            public System.DateTime RcvTime {
                get {
                    return this.rcvTimeField;
                }
                set {
                    this.rcvTimeField = value;
                    this.RaisePropertyChanged("RcvTime");
                }
            }
    
            [DataMember(Name = "ReplyTime", Order = 1)]
            public System.DateTime ReplyTime {
                get {
                    return this.replyTimeField;
                }
                set {
                    this.replyTimeField = value;
                    this.RaisePropertyChanged("ReplyTime");
                }
            }
    
            [DataMember(Name = "ClientRequestHandle", Order = 2)]
            public string ClientRequestHandle {
                get {
                    return this.clientRequestHandleField;
                }
                set {
                    this.clientRequestHandleField = value;
                    this.RaisePropertyChanged("ClientRequestHandle");
                }
            }
    
            [DataMember(Name = "RevisedLocaleID", Order = 3)]
            public string RevisedLocaleID {
                get {
                    return this.revisedLocaleIDField;
                }
                set {
                    this.revisedLocaleIDField = value;
                    this.RaisePropertyChanged("RevisedLocaleID");
                }
            }
    
            [DataMember(Name = "ServerState", Order = 4)]
            public serverState ServerState {
                get {
                    return this.serverStateField;
                }
                set {
                    this.serverStateField = value;
                    this.RaisePropertyChanged("ServerState");
                }
            }
    
            public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    
            protected void RaisePropertyChanged(string propertyName) {
                System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
                if ((propertyChanged != null)) {
                    propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
                }
            }
        }
    
    [DataContract(Namespace = "http://opcfoundation.org/webservices/XMLDA/1.0/", Name = "BrowseElement")]
        public class BrowseElement : INotifyPropertyChanged {
    
            private ItemProperty[] propertiesField;
    
            private string nameField;
    
            private string itemPathField;
    
            private string itemNameField;
    
            private bool isItemField;
    
            private bool hasChildrenField;
    
            [DataMember(Name = "Properties", Order = 0)]
            public ItemProperty[] Properties {
                get {
                    return this.propertiesField;
                }
                set {
                    this.propertiesField = value;
                    this.RaisePropertyChanged("Properties");
                }
            }
    
            [DataMember(Name = "Name", Order = 1)]
            public string Name {
                get {
                    return this.nameField;
                }
                set {
                    this.nameField = value;
                    this.RaisePropertyChanged("Name");
                }
            }
    
            [DataMember(Name = "ItemPath", Order = 2)]
            public string ItemPath {
                get {
                    return this.itemPathField;
                }
                set {
                    this.itemPathField = value;
                    this.RaisePropertyChanged("ItemPath");
                }
            }
    
            [DataMember(Name = "ItemName", Order = 3)]
            public string ItemName {
                get {
                    return this.itemNameField;
                }
                set {
                    this.itemNameField = value;
                    this.RaisePropertyChanged("ItemName");
                }
            }
    
            [DataMember(Name = "IsItem", Order = 4)]
            public bool IsItem {
                get {
                    return this.isItemField;
                }
                set {
                    this.isItemField = value;
                    this.RaisePropertyChanged("IsItem");
                }
            }
    
            [DataMember(Name = "HasChildren", Order = 5)]
            public bool HasChildren {
                get {
                    return this.hasChildrenField;
                }
                set {
                    this.hasChildrenField = value;
                    this.RaisePropertyChanged("HasChildren");
                }
            }
    
            public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    
            protected void RaisePropertyChanged(string propertyName) {
                System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
                if ((propertyChanged != null)) {
                    propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
                }
            }
    
        }
    
    [DataContract(Namespace = "http://opcfoundation.org/webservices/XMLDA/1.0/", Name = "OPCError")]
        public class OPCError : System.ComponentModel.INotifyPropertyChanged {
    
            private string textField;
    
            private System.Xml.XmlQualifiedName idField;
    
            [DataMember(Name = "Text", Order = 0)]
            public string Text {
                get {
                    return this.textField;
                }
                set {
                    this.textField = value;
                    this.RaisePropertyChanged("Text");
                }
            }
    
            [DataMember(Name = "ID", Order = 1)]
            public System.Xml.XmlQualifiedName ID {
                get {
                    return this.idField;
                }
                set {
                    this.idField = value;
                    this.RaisePropertyChanged("ID");
                }
            }
    
            public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    
            protected void RaisePropertyChanged(string propertyName) {
                System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
                if ((propertyChanged != null)) {
                    propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
                }
            }
        }
    

    C)WSDL(一部分,与类型定义有关的部分)

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:tns="http://opcfoundation.org/webservices/XMLDA/1.0/" targetNamespace="http://opcfoundation.org/webservices/XMLDA/1.0/" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="Browse">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="BrowseResponse">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="GetProperties">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="GetPropertiesResponse">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="GetStatus">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="GetStatusResponse">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="Read">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="ReadResponse">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="Subscribe">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="SubscribeResponse">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="SubscriptionCancel">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="SubscriptionCancelResponse">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="SubscriptionPolledRefresh">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="SubscriptionPolledRefreshResponse">
          <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
       <xs:element name="Write">-<xs:complexType><xs:sequence/></xs:complexType></xs:element>
          <xs:element name="WriteResponse">
             <xs:complexType>
             <xs:sequence/>
          </xs:complexType>
       </xs:element>
    </xs:schema>
    

    上面的内容包括在这里:

    <?xml version="1.0" encoding="UTF-8"?>
    <wsdl:definitions xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:tns="http://opcfoundation.org/webservices/XMLDA/1.0/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://opcfoundation.org/webservices/XMLDA/1.0/">
    <wsdl:types>
    <xsd:schema targetNamespace="http://opcfoundation.org/webservices/XMLDA/1.0/Imports">
    <xsd:import namespace="http://opcfoundation.org/webservices/XMLDA/1.0/" schemaLocation="http://localhost/OCXS/OCXS.svc?xsd=xsd0"/></xsd:schema></wsdl:types>
    <wsdl:message name="BrowseRequest"><wsdl:part name="parameters" element="tns:Browse"/></wsdl:message>
    <wsdl:message name="BrowseResponse"><wsdl:part name="parameters" element="tns:BrowseResponse"/></wsdl:message>
    <wsdl:message name="GetPropertiesRequest"><wsdl:part name="parameters" element="tns:GetProperties"/></wsdl:message>
    <wsdl:message name="GetPropertiesResponse"><wsdl:part name="parameters" element="tns:GetPropertiesResponse"/></wsdl:message>
    <wsdl:message name="GetStatusRequest"><wsdl:part name="parameters" element="tns:GetStatus"/></wsdl:message>
    <wsdl:message name="GetStatusResponse"><wsdl:part name="parameters" element="tns:GetStatusResponse"/></wsdl:message>
    <wsdl:message name="ReadRequest"><wsdl:part name="parameters" element="tns:Read"/></wsdl:message>-<wsdl:message name="ReadResponse"><wsdl:part name="parameters" element="tns:ReadResponse"/></wsdl:message>
    <wsdl:message name="SubscribeRequest"><wsdl:part name="parameters" element="tns:Subscribe"/></wsdl:message>
    <wsdl:message name="SubscribeResponse"><wsdl:part name="parameters" element="tns:SubscribeResponse"/></wsdl:message>
    <wsdl:message name="SubscriptionCancelRequest"><wsdl:part name="parameters" element="tns:SubscriptionCancel"/></wsdl:message><wsdl:message name="SubscriptionCancelResponse"><wsdl:part name="parameters" element="tns:SubscriptionCancelResponse"/></wsdl:message>
    <wsdl:message name="SubscriptionPolledRefreshRequest"><wsdl:part name="parameters" element="tns:SubscriptionPolledRefresh"/></wsdl:message>
    <wsdl:message name="SubscriptionPolledRefreshResponse"><wsdl:part name="parameters" element="tns:SubscriptionPolledRefreshResponse"/></wsdl:message>
    <wsdl:message name="WriteRequest"><wsdl:part name="parameters" element="tns:Write"/></wsdl:message>-<wsdl:message name="WriteResponse"><wsdl:part name="parameters" element="tns:WriteResponse"/></wsdl:message>
    <wsdl:portType name="IOCXSService">-<wsdl:operation name="Browse"><wsdl:input name="BrowseRequest" message="tns:BrowseRequest" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/Browse"/><wsdl:output name="BrowseResponse" message="tns:BrowseResponse" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/IOCXSService/BrowseResponse"/></wsdl:operation>
    <wsdl:operation name="GetProperties"><wsdl:input name="GetPropertiesRequest" message="tns:GetPropertiesRequest" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/GetProperties"/><wsdl:output name="GetPropertiesResponse" message="tns:GetPropertiesResponse" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/IOCXSService/GetPropertiesResponse"/></wsdl:operation>
    <wsdl:operation name="GetStatus"><wsdl:input name="GetStatusRequest" message="tns:GetStatusRequest" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/GetStatus"/><wsdl:output name="GetStatusResponse" message="tns:GetStatusResponse" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/IOCXSService/GetStatusResponse"/></wsdl:operation>
    <wsdl:operation name="Read"><wsdl:input name="ReadRequest" message="tns:ReadRequest" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/Read"/><wsdl:output name="ReadResponse" message="tns:ReadResponse" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/IOCXSService/ReadResponse"/></wsdl:operation>-<wsdl:operation name="Subscribe"><wsdl:input name="SubscribeRequest" message="tns:SubscribeRequest" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/Subscribe"/><wsdl:output name="SubscribeResponse" message="tns:SubscribeResponse" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/IOCXSService/SubscribeResponse"/></wsdl:operation>
    <wsdl:operation name="SubscriptionCancel"><wsdl:input name="SubscriptionCancelRequest" message="tns:SubscriptionCancelRequest" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/SubscriptionCancel"/><wsdl:output name="SubscriptionCancelResponse" message="tns:SubscriptionCancelResponse" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/IOCXSService/SubscriptionCancelResponse"/></wsdl:operation>
    <wsdl:operation name="SubscriptionPolledRefresh"><wsdl:input name="SubscriptionPolledRefreshRequest" message="tns:SubscriptionPolledRefreshRequest" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/SubscriptionPolledRefresh"/><wsdl:output name="SubscriptionPolledRefreshResponse" message="tns:SubscriptionPolledRefreshResponse" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/IOCXSService/SubscriptionPolledRefreshResponse"/></wsdl:operation>
    <wsdl:operation name="Write"><wsdl:input name="WriteRequest" message="tns:WriteRequest" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/Write"/><wsdl:output name="WriteResponse" message="tns:WriteResponse" wsaw:Action="http://opcfoundation.org/webservices/XMLDA/1.0/IOCXSService/WriteResponse"/></wsdl:operation></wsdl:portType></wsdl:definitions>
    

    注意: 如果我从MessageContractBrowseResponse删除了BrowseRequest属性(两者都被删除了,那么运行时会变得疯狂),问题仍然存在...... 这真的是关于消息合同的问题???

    可能解决方案

    好的每个人,也许我能看到光明...... 如果我删除所有DataContract(s)和ServiceContract(s)属性名称空间和名称(始终没有MessageContract(s)),一切正常。好吧,我得到了wsdl和类型,但是甚至与它们一起工作(但总是没有MessageContract(s))。 这就是原因(我想得到你的确认):

    我指定的命名空间:http://opcfoundation.org/webservices/XMLDA/1.0/不是一个简单的名称,在这里,您可以找到我的操作和类型(已定义)的WSDL定义。我的svc没有使用类型生成完整的WSDL定义,因为我已经在我提供的命名空间中定义了它!

    您如何看待这个?

2 个答案:

答案 0 :(得分:4)

除了[MessageContract]之外,您还将类BrowseDesponse定义为[DataContract]。基于你所说的,似乎[MessageContract]优先(这是有道理的 - [MC]定义消息的SOAP信封,可以包含成员,这些成员可以是数据合同。消息合同的成员定义为[MessageHeader][MessageBodyMember]属性,并且由于您没有,因此合同基本上是空的。

您没有显示BrowseRequest的定义,但由于您在请求中使用[MC]类型,您还需要在响应中使用[MC],所以我假设它具有相同的问题

答案 1 :(得分:0)

这是非常老的线索,但也许这有助于某人。

我们的客户端有一个.NET 2.0应用程序,我们创建了一个.NET 4 WCF项目。有一些C#类代表复杂类型。当客户端应用程序添加了WebReference并通过数据发送时,我们发现一些属性不是序列化,例如十进制,最终我们不得不将Serializer从默认的序列化程序更改为XmlSerializerFormat,这允许我们使用常规XML Serializer而不是WCF DataContractSerializer序列化类。

本文对MSDN非常有帮助 https://msdn.microsoft.com/en-us/library/ms733901(v=vs.110).aspx

参见下面的示例,我们没有使用WCF合同属性来允许与Webservices的交互。

<ServiceContract()>
<XmlSerializerFormat()>
Public Interface IService    
    <OperationContract()>
    <WebMethod()>
    Function CreateLoan(ByVal LoanRequest As LoanAccount) As String
End Interface

//C# Class
public class LoanAccount
{
    [XmlElement]
    public string New { get; set; }

    [XmlElement]
    public String CustomerNo { get; set; }

    [XmlElement]
    public string AcctType { get; set; }
}