2016-08-03 66 views
1

我有一個wcf服務(使用xmlserialization)。 有一些類,它看起來在了SoapUI這樣的:IXmlSerializable實現後的WCF服務xsd不正確

 <MyClass> 
     <propertyA>?</propertyA> 
     <propertyB>?</propertyB> 
    </MyClass> 

我不得不實施它IXmlSerializable的接口。 這件事以後,類在了SoapUI奇怪的結構:

 <MyClass> 
     <xs:schema> 
      <!--Ignoring type [{http://www.w3.org/2001/XMLSchema}schema]--> 
     </xs:schema> 
     <!--You may enter ANY elements at this point--> 
    </MyClass> 

願它是以下實施的getSchema方法的結果?

public XmlSchema GetSchema() 
    { 
     return null; 
    } 

下面是關於MyClass的從服務WSDL部分:

<xs:element name="MyClass" form="unqualified" maxOccurs="1" minOccurs="0"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element ref="xs:schema"/> 
     <xs:any/> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

回答

1

GetSchema()應該總是返回null。見Proper way to implement IXmlSerializable?

相反,你需要添加[XmlSchemaProvider(string methodName)]到您的類並實現返回XML模式和(匿名類型或XmlSchemaType)的XmlQualifiedName指定類型的模式的靜態方法。

舉例來說,如果你原來的類型是這樣的:

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/Question38741035")] 
[XmlRoot(Namespace = "http://schemas.datacontract.org/2004/07/Question38741035")] 
public class MyClass 
{ 
    [DataMember] 
    public string PropertyA { get; set; } 

    [DataMember] 
    public decimal PropertyB { get; set; } 
} 

然後你IXmlSerializable重新執行的類型應該是這個樣子:

[XmlSchemaProvider("GetSchemaMethod")] 
[XmlRoot(Namespace = "http://schemas.datacontract.org/2004/07/Question38741035")] 
public class MyClass : IXmlSerializable 
{ 
    public string PropertyA { get; set; } 

    public decimal PropertyB { get; set; } 

    const string XmlNamespace = "http://schemas.datacontract.org/2004/07/Question38741035"; 

    // This is the method named by the XmlSchemaProviderAttribute applied to the type. 
    public static XmlQualifiedName GetSchemaMethod(XmlSchemaSet xs) 
    { 
     string schema = @"<?xml version=""1.0"" encoding=""utf-16""?> 
<xs:schema 
    xmlns:tns=""http://schemas.datacontract.org/2004/07/Question38741035"" 
    elementFormDefault=""qualified"" 
    targetNamespace=""http://schemas.datacontract.org/2004/07/Question38741035"" 
    xmlns:xs=""http://www.w3.org/2001/XMLSchema""> 
    <xs:complexType name=""MyClass""> 
    <xs:sequence> 
     <xs:element minOccurs=""0"" name=""PropertyA"" nillable=""true"" type=""xs:string"" /> 
     <xs:element minOccurs=""0"" name=""PropertyB"" type=""xs:decimal"" /> 
    </xs:sequence> 
    </xs:complexType> 
    <xs:element name=""MyClass"" nillable=""true"" type=""tns:MyClass"" /> 
</xs:schema>"; 

     using (var textReader = new StringReader(schema)) 
     using (var schemaSetReader = System.Xml.XmlReader.Create(textReader)) 
     { 
      xs.Add(XmlNamespace, schemaSetReader); 
     } 
     return new XmlQualifiedName("MyClass", XmlNamespace); 
    } 

    #region IXmlSerializable Members 

    public System.Xml.Schema.XmlSchema GetSchema() 
    { 
     return null; 
    } 

    public void ReadXml(System.Xml.XmlReader reader) 
    { 
     if (reader.IsEmptyElement) 
     { 
      reader.Read(); 
      return; 
     } 

     var node = (XElement)XNode.ReadFrom(reader); 
     if (node != null) 
     { 
      var ns = (XNamespace)XmlNamespace; 

      PropertyA = (string)node.Element(ns + "PropertyA"); 
      PropertyB = (decimal)node.Element(ns + "PropertyB"); 
     } 
    } 

    public void WriteXml(System.Xml.XmlWriter writer) 
    { 
     if (PropertyA != null) 
      writer.WriteElementString("PropertyA", XmlNamespace, PropertyA); 
     writer.WriteStartElement("PropertyB", XmlNamespace); 
     writer.WriteValue(PropertyB); 
     writer.WriteEndElement(); 
    } 

    #endregion 
} 

這裏,我已經嵌入了預期的模式爲類型內的字符串文字。或者,您可以從磁盤加載它或通過反射來構建它。