Проблемы сериализации типов для .NET WCF Service: служба WSDL определяет пустые типы в XSD - PullRequest
5 голосов
/ 07 июня 2011

Я пишу веб-сервис с использованием WCF.

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

А2) Реализация сервиса:

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>

Примечание: Если я удаляю атрибут MessageContract из BrowseResponse и BrowseRequest (оба удаляются, иначе среда выполнения сходит с ума), проблема не исчезает .... Действительно ли это проблема, касающаяся контрактов на сообщения ???

МОЖЕТ БЫТЬ РЕШЕНИЕ

Ладно, может, я увижу свет ... Если я удаляю все пространство имен и имен атрибутов DataContract (s) и ServiceContract (s) (всегда без MessageContract (s)), все работает. Ну, я получаю wsdl и типы, но я работал даже с ними (но всегда без MessageContract (s)). Вот почему (я хотел бы получить от вас подтверждение):

Пространство имен, которое я указал: http://opcfoundation.org/webservices/XMLDA/1.0/ - не простое имя, ну, здесь вы можете найти определения WSDL для моих операций и типов (уже определены). Мой svc не генерирует полные определения WSDL с типами, ПОТОМУ ЧТО ЭТО УЖЕ ОПРЕДЕЛЕНО в указанном мною пространстве имен !!!

Что вы думаете об этом?

Ответы [ 2 ]

4 голосов
/ 07 июня 2011

Вы определили класс BrowseResponse как [MessageContract], в дополнение к [DataContract].Исходя из того, что вы говорите, кажется, что [MessageContract] имеет приоритет (что имеет смысл - [MC] определяет конверт SOAP для сообщения, который может содержать членов , и эти члены могут быть контрактами данных. Члены контрактов сообщений определяются с атрибутами [MessageHeader] или [MessageBodyMember], и, поскольку у вас их нет, контракт практически пустой.

Вы не показали определение BrowseRequest, нотак как вы используете тип [MC] в запросе, вам также нужно использовать [MC] в ответе, поэтому я предполагаю, что у него та же проблема.

0 голосов
/ 06 февраля 2016

Это очень старая тема, но, возможно, это кому-то поможет.

У нашего клиента было приложение .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 для взаимодействия с веб-сервисами.

<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; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...