Web Services Quiz: Issue 6 - the Answer

The answer to Issue 6 is maybe a bit surprising.

 

One of the keys for successfully answering the quiz lies in the understanding of XML schema types. In the given example, xsd:integer has been applied to the message’s elements. It’s important to understand, that xsd:integer represents an unbounded integer value with no restrictions in size or range.

Therefore this type can’t be mapped to an arithmetical CLR type:

 

xsd:integer ? System.Int16

xsd:integer ? System.Int32

xsd:integer ? System.Int64

xsd:integer ? System.*

When creating the proxy/stub code, wsdl.exe generates strings for the corresponding CLR type.

[XmlType(Namespace="https://beatsch/issue6/types")]

public class AddRequestMsgType

{

  [XmlElement(DataType="integer")]

  public string a;

  [XmlElement(DataType="integer")]

  public string b;

}

[XmlType(Namespace="https://beatsch/issue6/types")]

public class AddResponseMsgType

{

  [XmlElement(DataType="integer")]

  public string c;

}

Doing arithmetical tasks using strings isn’t a pleasure. Converting it to an integer may even result in the problem that the number is just too big to fit into the available memory layout. That’s why the proposed solution defines a separate type for handling unbounded integers:

public class UnboundedInteger

{

      private string _value="0";

   public UnboundedInteger(string init) {...}

      public UnboundedInteger(Int64 init) {...}

      static public UnboundedInteger operator + (UnboundedInteger lv, UnboundedInteger rv) {...}

      static public UnboundedInteger operator - (UnboundedInteger lv, UnboundedInteger rv) {...}

      static public UnboundedInteger operator * (UnboundedInteger lv, UnboundedInteger rv) {...}

      static public UnboundedInteger operator / (UnboundedInteger lv, UnboundedInteger rv) {...}

      static public implicit operator UnboundedInteger(Int64 value) {...}

      static public implicit operator Int64 (UnboundedInteger ui) {...}

      static public implicit operator string(UnboundedInteger ui) {...}

   }

[XmlType(Namespace="https://beatsch/issue6/types")]

public class AddRequestMsgType

{

  [XmlElement("a", DataType="integer")]

      public string _a="0";

      [XmlIgnore]

      public UnboundedInteger a

      {

            get { return new UnboundedInteger(_a);}

            set { _a = value;}

      }

   

      [XmlElement("b", DataType="integer")]

      public string _b="0";

      [XmlIgnore]

      public UnboundedInteger b

      {

            get { return new UnboundedInteger(_b);}

            set { _b = value;}

      }

}

[XmlType(Namespace="https://beatsch/issue6/types")]

public class AddResponseMsgType

{

      [XmlElement("c", DataType="integer")]

      public string _c="0";

      [XmlIgnore]

      public UnboundedInteger c

      {

            get { return new UnboundedInteger(_c);}

            set { _c = value;}

      }

}

The Issue’s quintessence

It’s pretty obvious that this is far away from an ideal solution. Therefore, use unbounded types only if you really require them. In most cases there exist predefined restricted types which map much better to programming languages. Think about the unrestricted types like abstract base classes that require additional refinement.

In the given example the better schema would use xsd.int instead:

   <xsd:schema targetNamespace="https://beatsch/issue6/types"

        xmlns:tns="https://beatsch/issue6/types"

        xmlns:xsd="https://www.w3.org/2001/XMLSchema">

        <xsd:complexType name="AddRequestMsgType">

           <xsd:sequence>

   <xsd:element maxOccurs="1" minOccurs="1" name="a" type="xsd:int" />

              <xsd:element maxOccurs="1" minOccurs="1" name="b" type="xsd:int" />

           </xsd:sequence>

        </xsd:complexType>

        <xsd:complexType name="AddResponseMsgType">

           <xsd:sequence>

              <xsd:element maxOccurs="1" minOccurs="1" name="c" type="xsd:int" />

           </xsd:sequence>

        </xsd:complexType>

   </xsd:schema>