Not too many of our customers have complained in the past that there is no
way to express null values for value types in .NET. Well, this is just the concept
of value types, isn’t it? But it is an essential piece that is missing
when working with XML schema-based types that allow null values. The .NET Framework
2.0 provides a solution for this.
Take a look at the following XML fragment that denotes a valid order:
<OrderStatus>
<Id>42</Id>
<OrderDate>2004-07-07</OrderDate>
<ShipDate xsi:nil="true"/>
</OrderStatus>
Again, imagine our fits-it-all Web service to deliver information about order
status. Based on the query criteria, the service may return the status of an
order that has not been shipped yet. In this case the Web service returns a
ShipDate element with the XSD instance attribute nil set
to true.
The current version of the .NET Framework, or more correctly the proxy class
generation and serialization process, already supports this. When you have an
XSD or WSDL with a nillable or optional element, the proxy class contains an
additional flag. In our example above this would be ShipDateSpecified.
This flag indicates whether the value for this element is set or not. People
need to be able to differentiate whether the element or attribute was missing
from the XML document and whether the attribute was present but had the default
value. The support for truly nullable types in the .NET Framework would make
things a lot easier. Take a look at the following Web service code:
[WebServiceBinding(
ConformanceClaims = WsiClaims.BP10,
EmitConformanceClaims = true)]
[WebService(Namespace = "http://www.thinktecture.com/demos/Nullable")]
public class NullableService
{
[WebMethod]
[return:XmlElement("MyData", IsNullable=true)]
public SqlInt32 GetData(bool ReturnNull)
{
SqlInt32 mydata;
mydata=(ReturnNull ? SqlInt32.Null : 1234);
return mydata;
}
}
This WebMethod returns a type of SqlInt32.
After a quick look into the documentation we can see that it implements INullable.
This is the essential interface that has to be supported when implementing your
own nullable types. If we point wsdl.exe to the service’s interface
and message contract it will generate the following code snippet:
[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"http://www.thinktecture.com/demos/Nullable/GetData",
RequestNamespace="http://www.thinktecture.com/demos/Nullable",
ResponseNamespace="http://www.thinktecture.com/demos/Nullable",
Use=System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("MyData", IsNullable=true)]
public System.Nullable<System.Int32> GetData(bool ReturnNull)
{
object[] results = this.Invoke("GetData", new object[]
{ReturnNull});
return ((System.Nullable<System.Int32>)(results[0]));
}
As can be seen very clear, the proxy uses a generic type System.Nullable<System.Int32>
to indicate that the actual instance of the return type may be null.
SqlTypes is also an example of a type that implements
IXmlSerializable. The
SQL types like SqlInt32
can then emit their own schemas and serialize/deserialize themselves. If we
specify a special switch on proxy generation, the wsdl.exe tool can map nillable
elements of primitive types (e.g. Int32,
Date) to SqlTypes.
So if you want to consume the above service, you might run wsdl.exe
with the /sqltypes switch to get a proxy class that contains this code:
[return: System.Xml.Serialization.XmlElementAttribute("TheData",
IsNullable=true)]
public SqlInt32 GetData(bool ReturnNull)
{
object[] results = this.Invoke("GetData", new object[]
{ReturnNull});
return ((System.Data.SqlTypes.SqlInt32)(results[0]));
}
Now we have a SqlInt32 data
type present as return type of the method. This can come in handy when you are
developing database-oriented and a bit more tightly coupled systems than it
originally was intended by the Web services credo.
About the author
Christian Weyer
Blog: http://weblogs.asp.net/cweyer/
Christian Weyer is co-founder of thinktecture (http://www.thinktecture.com/), a company aiding software architects and developers in realizing projects with .NET and distributed applications technologies. He is a recognized XML, Web Services and service-orientation expert. As a Microsoft MVP and one of the few independent Microsoft Regional Directors, he has made a name for himself in the developer community. He has spoken at many well-known developer conferences and forums worldwide and is a published author, editor and writer of numerous articles for various German and international technical magazines.
|