Connect with Expertise | Find Experts, Get Answers, Share Insights

Consuming WebService which returns NULL-values

Markus Eßmayr
 
Posts: n/a
#1: Nov 21 '05
Hello,

I'd like to consume a WebService, which returns an array of objects which
include several members of type System.String, System.Decimal and
System.DateTime.
In the WSDL-file, the members of the object are marked as nilable.
I generated the client classes using VS.NET 2003. After the creation, I got
the class-definition of the objects returned by the WebService too. BUT,
only the System.String members where marked to be nullable, System.Decimal
and System.DateTime don't. Ok, I know, they are value-types and cannot be
NULL, but thats exactly my problem.
If I then call the service, and it returns, I get an System.InvalidOperation
exception.
If I change the datatypes of the decimal and datetime-members to
System.Object, everything works, but I have to do the value-conversion
myself.

Is there a better way for solving that problem? I don't want to edit the
generated files everytime I regenerate them.

Thanks very much!
Max



Dino Chiesa [Microsoft]
 
Posts: n/a
#2: Nov 21 '05

re: Consuming WebService which returns NULL-values


There is a convention in .NET XML Serialization (which is used by the
webservices runtime) that allows value-types to be marked as "nil".
The convention is, for each property in a class with a name "propertyName",
if there is a companion property named "propertyNameSpecified" which is a
bool, then the propertyNameSpecified indicates whether the property of name
"propertyName" is nil or not.

See
http://msdn.microsoft.com/library/en...ClassTopic.asp
for the doc on this.

For example, this complexType in XML Schema:
<s:complexType name="IdType">
<s:sequence>
<s:element name="Name" minOccurs="0" maxOccurs="1"
type="s:string" nillable="true" />
<s:element name="Stamp" minOccurs="0" maxOccurs="1"
type="s:date" nillable="true" />
<s:element name="Id" minOccurs="0" maxOccurs="1"
type="s:int" nillable="true" />
</s:sequence>
</s:complexType>

will generate something like this type definition in C#:

[XmlType(Namespace="urn:myNameSpaceHere")]
public class IdType {
[XmlElement(IsNullable=true)] public string Name;

[XmlElement(DataType="date")] public System.DateTime Stamp;
[XmlIgnore] public bool StampSpecified;

[XmlElement] public int Id;
[XmlIgnore] public bool IdSpecified;
}

---------

Notice that the string (not a value type) is marked IsNillable=true, while
the int and DateTime (both value types) are not. In your app code, to
deal with nil values in the string, you do this:

if (instance.Name != null) ...

Conversely, to deal with nil values on value types (like the int and
DateTime), what you need to do is

if (instance.StampSpecified) ....
if (instance.IdSpecified) ....

The Id and Stamp will never actually be nil, but you treat them as nil in
app code if the flag says that they are not specified. The same convention
applies to all value types in .NET.

--------

So, can you examine the generated files and tell me if you have the
companion xxxSpecified properties marked "XmlIgnore"? If so, then you
know what to do. . .

-Dino




"Markus Eßmayr" <essmayr/at/racon-linz.at> wrote in message
news:%23vwcyhTdEHA.3076@TK2MSFTNGP10.phx.gbl...[color=blue]
> Hello,
>
> I'd like to consume a WebService, which returns an array of objects which
> include several members of type System.String, System.Decimal and
> System.DateTime.
> In the WSDL-file, the members of the object are marked as nilable.
> I generated the client classes using VS.NET 2003. After the creation, I[/color]
got[color=blue]
> the class-definition of the objects returned by the WebService too. BUT,
> only the System.String members where marked to be nullable, System.Decimal
> and System.DateTime don't. Ok, I know, they are value-types and cannot be
> NULL, but thats exactly my problem.
> If I then call the service, and it returns, I get an[/color]
System.InvalidOperation[color=blue]
> exception.
> If I change the datatypes of the decimal and datetime-members to
> System.Object, everything works, but I have to do the value-conversion
> myself.
>
> Is there a better way for solving that problem? I don't want to edit the
> generated files everytime I regenerate them.
>
> Thanks very much!
> Max
>
>[/color]


Markus Eßmayr
 
Posts: n/a
#3: Nov 21 '05

re: Consuming WebService which returns NULL-values


Dino,

thanks for your reply!

We now added the "minOccurs" and "maxOccurs" settings into our WSDL-file and
updated the server- and client-classes. Now it works fine because it just
doesn't send the NULL-values to the client.
Previously we didn't specify these two attributes.

But, what if I absolutely don't have a chance to modify the server-WSDL?
Let's say that the attributes are specified like this:
<s:element name="Stamp" minOccurs="1" maxOccurs="1" type="s:date"
nillable="true" />

So I won't have a chance to consume this service the "easy" way!

I wonder why there is no functionality in the .NET serialization, which
supports something like
[XmlIgnore] public bool StampIsNull;

What do you think?

Max


"Dino Chiesa [Microsoft]" <dinoch@online.microsoft.com> wrote in message
news:uJPqDAXdEHA.3632@TK2MSFTNGP09.phx.gbl...[color=blue]
> There is a convention in .NET XML Serialization (which is used by the
> webservices runtime) that allows value-types to be marked as "nil".
> The convention is, for each property in a class with a name[/color]
"propertyName",[color=blue]
> if there is a companion property named "propertyNameSpecified" which is a
> bool, then the propertyNameSpecified indicates whether the property of[/color]
name[color=blue]
> "propertyName" is nil or not.
>
> See
>[/color]
http://msdn.microsoft.com/library/en...ClassTopic.asp[color=blue]
> for the doc on this.
>
> For example, this complexType in XML Schema:
> <s:complexType name="IdType">
> <s:sequence>
> <s:element name="Name" minOccurs="0" maxOccurs="1"
> type="s:string" nillable="true" />
> <s:element name="Stamp" minOccurs="0" maxOccurs="1"
> type="s:date" nillable="true" />
> <s:element name="Id" minOccurs="0" maxOccurs="1"
> type="s:int" nillable="true" />
> </s:sequence>
> </s:complexType>
>
> will generate something like this type definition in C#:
>
> [XmlType(Namespace="urn:myNameSpaceHere")]
> public class IdType {
> [XmlElement(IsNullable=true)] public string Name;
>
> [XmlElement(DataType="date")] public System.DateTime Stamp;
> [XmlIgnore] public bool StampSpecified;
>
> [XmlElement] public int Id;
> [XmlIgnore] public bool IdSpecified;
> }
>
> ---------
>
> Notice that the string (not a value type) is marked IsNillable=true, while
> the int and DateTime (both value types) are not. In your app code, to
> deal with nil values in the string, you do this:
>
> if (instance.Name != null) ...
>
> Conversely, to deal with nil values on value types (like the int and
> DateTime), what you need to do is
>
> if (instance.StampSpecified) ....
> if (instance.IdSpecified) ....
>
> The Id and Stamp will never actually be nil, but you treat them as nil in
> app code if the flag says that they are not specified. The same[/color]
convention[color=blue]
> applies to all value types in .NET.
>
> --------
>
> So, can you examine the generated files and tell me if you have the
> companion xxxSpecified properties marked "XmlIgnore"? If so, then you
> know what to do. . .
>
> -Dino
>
>
>
>
> "Markus Eßmayr" <essmayr/at/racon-linz.at> wrote in message
> news:%23vwcyhTdEHA.3076@TK2MSFTNGP10.phx.gbl...[color=green]
> > Hello,
> >
> > I'd like to consume a WebService, which returns an array of objects[/color][/color]
which[color=blue][color=green]
> > include several members of type System.String, System.Decimal and
> > System.DateTime.
> > In the WSDL-file, the members of the object are marked as nilable.
> > I generated the client classes using VS.NET 2003. After the creation, I[/color]
> got[color=green]
> > the class-definition of the objects returned by the WebService too. BUT,
> > only the System.String members where marked to be nullable,[/color][/color]
System.Decimal[color=blue][color=green]
> > and System.DateTime don't. Ok, I know, they are value-types and cannot[/color][/color]
be[color=blue][color=green]
> > NULL, but thats exactly my problem.
> > If I then call the service, and it returns, I get an[/color]
> System.InvalidOperation[color=green]
> > exception.
> > If I change the datatypes of the decimal and datetime-members to
> > System.Object, everything works, but I have to do the value-conversion
> > myself.
> >
> > Is there a better way for solving that problem? I don't want to edit the
> > generated files everytime I regenerate them.
> >
> > Thanks very much!
> > Max
> >
> >[/color]
>
>
>[/color]


Dino Chiesa [Microsoft]
 
Posts: n/a
#4: Nov 21 '05

re: Consuming WebService which returns NULL-values



"Markus Eßmayr" <essmayr/at/racon-linz.at> wrote in message
news:uqbyKcXdEHA.2812@tk2msftngp13.phx.gbl...
[color=blue]
> But, what if I absolutely don't have a chance to modify the server-WSDL?
> Let's say that the attributes are specified like this:
> <s:element name="Stamp" minOccurs="1" maxOccurs="1" type="s:date"[/color]
nillable="true" />[color=blue]
>
> So I won't have a chance to consume this service the "easy" way!
>[/color]

Let's not discuss whether it actually makes sense to have a minOccurs=1
element be nillable. Suppose that it does make sense.
Generating a proxy class from this WSDL will NOT generate the StampSpecified
bool property.

This seems broken. However, you can easily add it in yourself. (I know you
said you did not want to modify the generated files, but the point is you
could do so)

The other option is to modify the server-side WSDL before you use it to
generate code. I often do this to rename artifacts or fixup things that I
know, through testing, are broken. For example, a service is sending an
xsd:date, but the WSDL specifies an xsd:dateTime. And so on. So you
could just snapshot the WSDL and tweak it a bit.

[color=blue]
> I wonder why there is no functionality in the .NET serialization, which
> supports something like
> [XmlIgnore] public bool StampIsNull;
>
> What do you think?[/color]

How would this be different from the StampSpecified mechanism that is
currently supported ?

-D


Markus Eßmayr
 
Posts: n/a
#5: Nov 21 '05

re: Consuming WebService which returns NULL-values


Please see below ...

Max

"Dino Chiesa [Microsoft]" <dinoch@online.microsoft.com> wrote in message
news:uWFi9iYdEHA.212@TK2MSFTNGP12.phx.gbl...[color=blue]
>
> "Markus Eßmayr" <essmayr/at/racon-linz.at> wrote in message
> news:uqbyKcXdEHA.2812@tk2msftngp13.phx.gbl...
>[color=green]
> > But, what if I absolutely don't have a chance to modify the server-WSDL?
> > Let's say that the attributes are specified like this:
> > <s:element name="Stamp" minOccurs="1" maxOccurs="1" type="s:date"[/color]
> nillable="true" />[color=green]
> >
> > So I won't have a chance to consume this service the "easy" way!
> >[/color]
>
> Let's not discuss whether it actually makes sense to have a minOccurs=1
> element be nillable. Suppose that it does make sense.
> Generating a proxy class from this WSDL will NOT generate the[/color]
StampSpecified[color=blue]
> bool property.
>
> This seems broken. However, you can easily add it in yourself. (I know[/color]
you[color=blue]
> said you did not want to modify the generated files, but the point is you
> could do so)
>
> The other option is to modify the server-side WSDL before you use it to
> generate code. I often do this to rename artifacts or fixup things that I
> know, through testing, are broken. For example, a service is sending an
> xsd:date, but the WSDL specifies an xsd:dateTime. And so on. So you
> could just snapshot the WSDL and tweak it a bit.
>
>[color=green]
> > I wonder why there is no functionality in the .NET serialization, which
> > supports something like
> > [XmlIgnore] public bool StampIsNull;
> >
> > What do you think?[/color]
>
> How would this be different from the StampSpecified mechanism that is
> currently supported ?[/color]

The problem is: If I'm not able to make changes to the server side WSDL
(if I use a service offered by a 3rd party company, which doesn't want to
modify it and more), and they have minOccurs="1" (or lets say, they just
forgot to make the minOccurs definition, which I think defaults to 1),
they send the fields containing a null value. Now, AFAIK, .NET is NOT
able to consume this service! Even that NULL values are included in the
XML specification, it won't be possible to consume that service, because
the field does come down from the server (StampSpecified=true), BUT
it contains NULL, which cannot be mapped to any System.DateTime.
Here a StampIsNull=true would help a lot.

But I just read about the nullable types in .NET 2.0. Maybe there is some
solution for this!

[color=blue]
>
> -D
>
>
>[/color]


Dino Chiesa [Microsoft]
 
Posts: n/a
#6: Nov 21 '05

re: Consuming WebService which returns NULL-values



"Markus Eßmayr" <essmayr/at/racon-linz.at> wrote in message
news:u0XzFWgdEHA.1652@TK2MSFTNGP09.phx.gbl...[color=blue]
> Please see below ...[/color]
[color=blue]
> The problem is: If I'm not able to make changes to the server side WSDL
> (if I use a service offered by a 3rd party company, which doesn't want to
> modify it and more), and they have minOccurs="1" (or lets say, they just
> forgot to make the minOccurs definition, which I think defaults to 1),
> they send the fields containing a null value. Now, AFAIK, .NET is NOT
> able to consume this service! Even that NULL values are included in the
> XML specification, it won't be possible to consume that service, because
> the field does come down from the server (StampSpecified=true), BUT
> it contains NULL, which cannot be mapped to any System.DateTime.
> Here a StampIsNull=true would help a lot.
>[/color]

Ahh, ok, I see. Yes, you are correct.
You are getting from the server
<Stamp isNil="true" />

in which case, the XML Serializer chokes. So you would need to do some
fancy footwork on the client side in order to de-serialize a nil DateTime.
[color=blue]
> But I just read about the nullable types in .NET 2.0. Maybe there is some
> solution for this!
>[/color]
yes, in 2.0.
In v1.1, I think you have work to do. It is not easy, but it is possible.

This is the default definition for a <xsd:dateTime> .

public class MyType {
public System.DateTime DateTimeField;
}

If you modify it to something like this, you may get the behavior you want:
public class MyType {
private static string formatString= "yyyy-MM-ddTHH:mm:ss.fffffffzzz";
private static System.Globalization.CultureInfo CInfo= new
System.Globalization.CultureInfo("en-US", true);

[XmlIgnore] public System.DateTime internal_DateTimeField;
[XmlIgnore] public bool DateTimeFieldIsNull; // ideally this would be
provided by .NET, but it isn't.

[XmlElement(IsNullable=true)]
public string DateTimeField {
set {
if ((value!=null) && (value != "")) {
internal_DateTimeField= System.DateTime.ParseExact(value,
formatString, CInfo);
DateTimeFieldIsNull= false;
}
else
DateTimeFieldIsNull= true;
}
get {
return (DateTimeFieldIsNull) ?
null :
internal_DateTimeField.ToString(formatString) ;
}
}
}


-D


Markus Eßmayr
 
Posts: n/a
#7: Nov 21 '05

re: Consuming WebService which returns NULL-values


Thanks very much for your answer.
I'll try to use it somehow, but it'll take a while! ;-)

Max

"Dino Chiesa [Microsoft]" <dinoch@online.microsoft.com> wrote in message
news:eLknFVkdEHA.3512@TK2MSFTNGP12.phx.gbl...[color=blue]
>
> "Markus Eßmayr" <essmayr/at/racon-linz.at> wrote in message
> news:u0XzFWgdEHA.1652@TK2MSFTNGP09.phx.gbl...[color=green]
> > Please see below ...[/color]
>[color=green]
> > The problem is: If I'm not able to make changes to the server side WSDL
> > (if I use a service offered by a 3rd party company, which doesn't want[/color][/color]
to[color=blue][color=green]
> > modify it and more), and they have minOccurs="1" (or lets say, they just
> > forgot to make the minOccurs definition, which I think defaults to 1),
> > they send the fields containing a null value. Now, AFAIK, .NET is NOT
> > able to consume this service! Even that NULL values are included in the
> > XML specification, it won't be possible to consume that service, because
> > the field does come down from the server (StampSpecified=true), BUT
> > it contains NULL, which cannot be mapped to any System.DateTime.
> > Here a StampIsNull=true would help a lot.
> >[/color]
>
> Ahh, ok, I see. Yes, you are correct.
> You are getting from the server
> <Stamp isNil="true" />
>
> in which case, the XML Serializer chokes. So you would need to do some
> fancy footwork on the client side in order to de-serialize a nil DateTime.
>[color=green]
> > But I just read about the nullable types in .NET 2.0. Maybe there is[/color][/color]
some[color=blue][color=green]
> > solution for this!
> >[/color]
> yes, in 2.0.
> In v1.1, I think you have work to do. It is not easy, but it is[/color]
possible.[color=blue]
>
> This is the default definition for a <xsd:dateTime> .
>
> public class MyType {
> public System.DateTime DateTimeField;
> }
>
> If you modify it to something like this, you may get the behavior you[/color]
want:[color=blue]
> public class MyType {
> private static string formatString= "yyyy-MM-ddTHH:mm:ss.fffffffzzz";
> private static System.Globalization.CultureInfo CInfo= new
> System.Globalization.CultureInfo("en-US", true);
>
> [XmlIgnore] public System.DateTime internal_DateTimeField;
> [XmlIgnore] public bool DateTimeFieldIsNull; // ideally this would[/color]
be[color=blue]
> provided by .NET, but it isn't.
>
> [XmlElement(IsNullable=true)]
> public string DateTimeField {
> set {
> if ((value!=null) && (value != "")) {
> internal_DateTimeField= System.DateTime.ParseExact(value,
> formatString, CInfo);
> DateTimeFieldIsNull= false;
> }
> else
> DateTimeFieldIsNull= true;
> }
> get {
> return (DateTimeFieldIsNull) ?
> null :
> internal_DateTimeField.ToString(formatString) ;
> }
> }
> }
>
>
> -D
>
>
>[/color]


Closed Thread