【问题标题】:Problems serializing types for a .NET WCF Service: Service WSDL defines empty types in XSD.NET WCF 服务的序列化类型问题:服务 WSDL 在 XSD 中定义空类型
【发布时间】:2011-09-09 14:31:33
【问题描述】:

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

  1. 我创建了数据合约。

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

  3. 我实现了创建服务类的服务契约。

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

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

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

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

发生了什么?

好像序列化失败了。

我提供一些:

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>

注意: 如果我从BrowseResponseBrowseRequest 中删除MessageContract 属性(两者都被删除,否则运行时变得疯狂),问题仍然存在...... 真的是messagecontracts的问题???

也许是解决方案

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

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

您对此有何看法?

【问题讨论】:

  • 你能发布一个DataContract的样本吗?它是否包含 Datamember 属性?
  • 那么请贴出一项的C#和WSDL。
  • WSDL 中是否还有关于 BrowseResponse 的部分?
  • 只有我现在发布的那个...抱歉缩进...
  • 但是,您对正在发生的事情有一个大致的了解吗?是关于命名空间的东西吗???还是什么???

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


【解决方案1】:

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

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

【讨论】:

  • 好的...让我尝试修复它...我会告诉您结果...请提出一个问题... MessageContract 的真正作用是什么?与 DataContract 有什么关系?
  • MessageContract 没有被广泛使用。当您希望请求/响应的某些部分进入 SOAP 主体,而某些部分进入 SOAP 标头(通常需要与现有服务的互操作性)时,通常会使用它 - 请参阅 msdn.microsoft.com/en-us/library/ms730255.aspx 了解更多信息。
  • 数据契约用于定义要在客户端和服务器之间交换的数据。消息契约中的成员可以是数据契约类型(反之则不然)。所以消息契约用来定义消息shape,而数据契约用来定义消息content。这是一般视图,主要用于指导 - 可以使用数据协定中的属性来定义“形状”(元素的顺序),也可以使用消息协定中的字段来定义内容。
  • 我删除了 MessageCOntractAttributes,,,,现在我在我的 wsdl 文件中看不到任何东西......没有类型,没有消息,什么都没有...... :( 如果我放回这些属性,没有任何变化(我向您保证我重新启动 IIS 并刷新我的服务主机)
  • 您可以尝试从一个空服务重新开始,然后仅添加 1 个操作(即 Browse),并分别定义 BrowseRequest 和 BrowseResponse 一个成员。然后浏览到 ?wsdl 页面。如果这有效(即,您看到了消息、类型),然后开始将它们添加回来,直到您遇到它停止工作的点。
【解决方案2】:

这是一个非常古老的线程,但也许这对某人有帮助。

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

这篇文章对 MSDN 很有帮助 https://msdn.microsoft.com/en-us/library/ms733901(v=vs.110).aspx

请参见下面的示例,我们没有使用 WCF 合同属性来允许与 Web 服务进行交互。

<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; }
}

【讨论】:

    猜你喜欢
    • 2012-11-28
    • 2011-07-14
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-07
    • 1970-01-01
    • 2012-01-25
    相关资源
    最近更新 更多