简体   繁体   中英

Problems serializing types for a .NET WCF Service: Service WSDL defines empty types in XSD

I am writing a web service using WCF.

  1. I created data contracts.

  2. I created my service contract (interface). I defined methods (whose parameters are typed as for the data contracts).

  3. I implemented the service contract creating a service class.

  4. I hosted my service using a svc file and IIS.

  5. I tried my service, looked for http://localhost/myvirtdiriis/myservice.svc --> The service was loaded, and a nice web page describing the presence of my service showed.

  6. I wanted to look at the WSDL. Using the provided link I can see that types are only defined, I can see just the types definition (like <complexType> ), but nothing inside (types are empty).

  7. I coded a simple client, a call to an operation went good, but when returning the type it is empty (internal fields have the construction values, while my service place some values there), for example, a call to an operation returning a type having three strings set by the operation contract method to "Hello", "Hello2" and "Hello3", returns the type having these strings set to "" (construction values, as if no changes happened).

What happened?

It seems that serialization fails.

I am providing some:

A1) A part of the service contract:

[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) The service implementation:

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

B) Types:

[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 (a part, the one concerning type definitions)

<?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>

The piece above is included here:

<?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>

NOTE: If I remove the MessageContract attribute from BrowseResponse and BrowseRequest (both removed otherwose the runtime gets crazy), the problem persists.... Is it really an issue concerning messagecontracts???

MAYBE THE SOLUTION

OK everybody, maybe I can see the light... If I remove all DataContract (s) and ServiceContract (s) attributes namespace and names (always without MessageContract (s)), everything works. Well, I get wsdl and types, but t worked even with them (but always without MessageContract (s)). Here's why (I would like to get confirm from you):

The namespace I specified: http://opcfoundation.org/webservices/XMLDA/1.0/ is not a simple name, well, here you can find WSDL definitions for my operations and types (already defined). My svc does not generate complete WSDL definitions with types BECAUSE IT ALREADY HAS THEM defined in that namespace I provided!!!

What do you think about this?

You defined the class BrowseResponse as a [MessageContract] , in addition to [DataContract] . Based on what you're saying, it seems like [MessageContract] takes precedence (which makes sense - [MC] defines the SOAP envelope for the message, which can contain members , and those members can be data contracts. Members of message contracts are defined with either [MessageHeader] or [MessageBodyMember] attributes, and since you don't have any, the contract is essentially empty.

You didn't show the definition of BrowseRequest, but since you're using a [MC] type in the request, you also need to use a [MC] in the response, so I'm assuming it has the same problem.

This is very old thread but maybe this helps someone.

Our client had a .NET 2.0 application and we created a .NET 4 WCF project. There were some C# classes that represent complex types. When the client application added WebReference and sent across the data we found some properties weren't serializing eg decimals, eventually we had to change the Serializer from the default serializer to XmlSerializerFormat which allowed us to serialize classes with regular XML Serializer and not the WCF DataContractSerializer.

This article was very helpful from MSDN https://msdn.microsoft.com/en-us/library/ms733901(v=vs.110).aspx

See example below, we used no WCF contract attributes to allow for the interaction with 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; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM