Экспорт схем WSDL/XSD для типов контрактов данных с помощью IXmlSerializable

Я создаю сервис WCF, который я хочу использовать из приложения Java. Но вопрос не о взаимодействии.net-java.

Ключевым моментом является один из типов, связанных с операцией сервиса - IXmlSerializable. Этот тип возвращает свою XSD-схему со статическим методом, на который ссылается XmlSchemaProviderAttribute. Проблема в том, что когда мы получаем wsdl для службы через mex-endpoint ( http:?wsdl), эта схема не возвращается.

Вот подробности.

Некоторые контракты на обслуживание wcf:

 [ServiceContract]
 public interface IService1
 {
  [OperationContract]
  DomainData GetData();
 }

Тип DomainData:

 [DataContract(Namespace = "http://schemas.biz.org/Samples/customserialization")]
 public class DomainData
 {
  [DataMember(Name = "AuxData")]
  Dictionary<String, AuxDomainData> m_auxData = new Dictionary<string, AuxDomainData>();

  [DataMember]
  public string ObjectId { get; set; }

  public IDictionary<string, AuxDomainData> AuxData
  {
   get { return m_auxData; }
  }
 }

Как вы можете видеть, DomainData содержит словарь объектов AuxDomainData, который:

 [XmlSchemaProvider("GetXmlSerializationSchema")]
 public class AuxDomainData : IXmlSerializable
 {
  [DataMember]
  public Object AuxData { get; set; }

  XmlSchema IXmlSerializable.GetSchema() { return null; }

  void IXmlSerializable.ReadXml(XmlReader reader) { }

  void IXmlSerializable.WriteXml(XmlWriter writer) { }

  public static string Namespace = "http://schemas.biz.org/Samples/customserialization";

  public static XmlQualifiedName GetXmlSerializationSchema(XmlSchemaSet schemas)
  {
   var qname =  new XmlQualifiedName("AuxDomainData", Namespace);
   string resourceName = "CustomSerialization.aux-domain-data.xsd";
   using (Stream stream = typeof(AuxDomainData).Assembly.GetManifestResourceStream(resourceName))
   {
    var schema = XmlSchema.Read(stream, null);
    schemas.Add(schema);
   }
   return qname;
  }
 }

Здесь мы возвращаем схему XSD в методе GetXmlSerializationSchema. Сама схема проста, но позвольте мне пропустить ее здесь.

Этот код прост, я думаю, это обычный сценарий для типов IXmlSerializable.

Теперь мы хотим WSDL. Я собираюсь использовать WSDL для создания Java-клиента с помощью Metro. Но на самом деле JDK 1.6 достаточно, так как он содержит стек WS (и wsimport.exe). Итак, Java хочет wsdl с определением wsdl: service. Вот почему я не могу дать ему wsdl из wsdl.exe (потому что wsdl, созданный wsdl, не содержит определения wsdl: service, только wsdl: portType). Итак, я вызываю wsimport.bat http://localhost/Service1.svc?wsdl

Но в результате я получаю следующее: [ОШИБКА] неопределенный простой или сложный тип 'q1:AuxDomainData', строка 1 из http://locahost/CustomSerialization/Service1.svc?xsd=xsd3

Это потому, что составной wsdl на самом деле не содержит такого типа, как AuxDomainData. Это правда, и мы не можем винить java/metro/ любой другой стек. Если мы посмотрим на wsdl, созданный wcf, он содержит элемент wsdl:types с импортом всех схем xsd:

<wsdl:types>
  <xsd:schema targetNamespace="http://tempuri.org/Imports">
    <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd0" namespace="http://tempuri.org/" /> 
    <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/" /> 
    <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd2" namespace="http://schemas.biz.org/Samples/customserialization" /> 
    <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd3" namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" /> 
  </xsd:schema>
</wsdl:types>

Я не приведу здесь все xsd, но дело в том, что в них нет определения AuxDomainData. Схема xsd для типа AuxDomainData находится в http://localhost/CustomSerialization/Service1.svc?xsd=xsd 4 "документе". Но, как вы видите, корень wsdl не содержит ссылки на него. Это проблема. Результирующий набор схем wsdl/xsd не завершен.

Итак, каковы мои варианты?

2 ответа

Решение

Вы уверены, что WSDL не ссылается на это? Обычно WCF включает элемент непосредственно перед списком элементов , примерно так:

<wsdl:types>
    <xsd:schema targetNamespace="http://tempuri.org/Imports">
        <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd0" namespace="http://tempuri.org/"/>
        <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>
        <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd2" namespace="http://schemas.datacontract.org/2004/07/MyServiceNamespace"/>
        <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd3" namespace="http://schemas.datacontract.org/2004/07/MyServiceNamespace.AnotherNamespace"/>
        <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd4" namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
    </xsd:schema>
</wsdl:types>

Проверьте это. Это должно быть там. Возможно, однако, что Java не распознает это.

Если это проблема, то есть способы сгладить WSDL. Вы можете попробовать это.

Кстати, конечной точкой mex обычно является Service1.svc / mex. WSDL немного отличается.

На самом деле, предлагаемое Аароном решение от " http://blogs.msdn.com/dotnetinterop/archive/2008/09/23/flatten-your-wsdl-with-this-custom-servicehost-for-wcf.aspx" превращается быть не совсем правильным. Не сама идея, а код. После использования этого ExportExtension для нескольких сервисов, запрашивающих wsdl для следующего по очереди сервиса, происходит сбой по причине дублирования типов.

Я также спросил на форуме msdn: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/0ea27bec-08cc-4a20-86ce-6e3477abb1c5.

Другие вопросы по тегам