Skip to content

Using xs:choice in WCF-Services

At the very beginning of the ongoing work of my "Projektgruppe" we had to convert an existing XSD into a DataContract compliant schema. The XSD was part of the WSDL of one of our services which we developed using a contract-first approach. One complex type contained a xs:choice element which is not supported by DataContracts (see Data Contract Schema Reference). Therefore we decided to change our XSD. Retrospectively, maybe this was not the best decision. We discussed the usage of polymorphism with the help of xsd extension but didn't use it at all.

Nevertheless, the good old XmlSerializer supports xs:choice! Here's a very simple example:

C#:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Runtime.Serialization;
  5. using System.ServiceModel;
  6. using System.Text;
  7. using System.Xml.Serialization;
  8. using System.Xml;
  9. using System.Xml.Schema;
  10.  
  11. namespace Choice
  12. {
  13.     [ServiceContract(Name="ChoiceService", Namespace="http://dev.janus-net.de/example/choice")]
  14.     [XmlSerializerFormat(Style = OperationFormatStyle.Document)]
  15.     public interface IChoiceService
  16.     {
  17.         [OperationContract()]
  18.         void DoSomething(XSDChoice choice);
  19.     }
  20.  
  21.     [ServiceBehavior(Name="ChoiceService", Namespace="http://dev.janus-net.de/example/choice")]
  22.     public class ChoiceService : IChoiceService
  23.     {
  24.         public void DoSomething(XSDChoice choice)
  25.         {
  26.             System.Console.WriteLine(choice.ToString());
  27.         }
  28.     }
  29.  
  30.     [Serializable]
  31.     public class XSDChoice
  32.     {
  33.  
  34.         [XmlChoiceIdentifier("ChoiceType")]
  35.         [XmlElement("Choice1", typeof(string), IsNullable = false)]
  36.         [XmlElement("Choice2", typeof(double), IsNullable = false)]
  37.         public object MyChoice;
  38.  
  39.         [XmlIgnore]
  40.         [XmlElement(IsNullable=false)]
  41.         public ItemChoiceType ChoiceType;
  42.  
  43.         public override string  ToString()
  44.         {
  45.             string info = null != MyChoice ?
  46.                 (":Type<" + MyChoice.GetType() + ">,Value<" + MyChoice.ToString() + ">")
  47.                 : (":Type<object>,Value<null>");
  48.             if (ChoiceType == ItemChoiceType.Choice1)
  49.             {
  50.                 return "Choice1:" + info;
  51.             }
  52.             else if (ChoiceType == ItemChoiceType.Choice2)
  53.             {
  54.                 return "Choice2:" + info;
  55.             }
  56.             else
  57.             {
  58.                 return info;
  59.             }
  60.         }
  61.     }
  62.  
  63.     [XmlType(IncludeInSchema = false)]
  64.     public enum ItemChoiceType
  65.     {
  66.         None,
  67.         Choice1,
  68.         Choice2
  69.     }
  70. }

This will result in the following XSD:

XML:
  1. <xs:complexType name="XSDChoice">
  2.     <xs:sequence>
  3.         <xs:choice minOccurs="1" maxOccurs="1">
  4.             <xs:element minOccurs="1" maxOccurs="1" name="Choice2" type="xs:double"/>
  5.             <xs:element minOccurs="0" maxOccurs="1" name="Choice1" type="xs:string"/>
  6.         </xs:choice>
  7.     </xs:sequence>
  8. </xs:complexType>

You can even do much more complex things using the XmlSerializer in conjunction with Service Contracts. Designing Service Contracts with WCF by Michele Leroux Bustamante gives a very very good introduction.

Categories: Programming, Web.

Tags: , , , , , , , , ,

Comment Feed

No Responses (yet)



Some HTML is OK

or, reply to this post via trackback.