I just ran into a little issue with a Web Service imported through the WCF Service Utility. The issue revolves around dates imported for a service. In the WSDL the layout looks like this:
<xsd:complexType name="NewEnrolment">
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="1" name="RequestEnrolmentAdvance" type="xsdLocal6:string1" />
<xsd:element minOccurs="0" maxOccurs="1" name="Type" type="xsdLocal6:string30" />
<xsd:element minOccurs="0" maxOccurs="1" name="StartDate" type="xsd:date" />
<xsd:element minOccurs="0" maxOccurs="1" name="ServiceType" type="xsdLocal6:string30" />
<xsd:element minOccurs="0" maxOccurs="1" name="ServiceProviderEnrolmentReference" type="xsdLocal6:string50" />
<xsd:element minOccurs="0" maxOccurs="1" name="EndDate" type="xsd:date" />
<xsd:element minOccurs="0" maxOccurs="1" name="ParentGuardianDateOfBirth" type="xsd:date" />
<xsd:element minOccurs="0" maxOccurs="1" name="ParentGuardianCRN" type="xsdLocal6:string10" />
<xsd:element minOccurs="0" maxOccurs="1" name="ChildDateOfBirth" type="xsd:date" />
<xsd:element minOccurs="0" maxOccurs="1" name="ChildCRN" type="xsdLocal6:string10" />
<xsd:element minOccurs="0" maxOccurs="1" name="CCBApprovalId" type="xsdLocal6:string15" />
</xsd:sequence>
</xsd:complexType>
When the type is imported and the .NET class is generated the type ends up having properties of the generated date field plus shadowed properties that with a Specified extension:
When I first ran this code and set these date variables I ended up NOT setting these specified fields and the service was complaining that the values were actually missing. That's somewhat unexpected behavior. Once I set the Specified fields to true for each date sent the service calls went through.
FWIW, the 'Specified' fields are stripped from the outgoing SOAP message (they are marked with XmlIgnoreAttribute in the generated code).
This seems an odd design choice. A nullable DateTime property would have been a much better type choice in this situation to specify whether a date is to be included or not. <shrug>
As it is I suppose I can add code to a service wrapper method (this service will be accessed from a non-.NET client anyway so a wrapper is used anyway) that automatically checks for these date values and sets the flag:
public Message_CreateEnrolment_Output NewEnrolment(Message_CreateEnrolment_Input input)
{
try
{
// *** Some fix up code to make it easier to call the service from the client
if (input.NewEnrolment.ChildDateOfBirth > DateTime.MinValue)
input.NewEnrolment.ChildDateOfBirthSpecified = true;
if (input.NewEnrolment.EndDate > DateTime.MinValue)
input.NewEnrolment.EndDateSpecified = true;
if (input.NewEnrolment.StartDate > DateTime.MinValue)
input.NewEnrolment.StartDateSpecified = true;
if (input.NewEnrolment.ParentGuardianDateOfBirth > DateTime.MinValue)
input.NewEnrolment.ParentGuardianDateOfBirthSpecified = true;
// *** Create an instance of the Service Proxy
EnrolmentInterface_Binding_FaCSIAEnrolmentInterfaceClient client =
this.GetEnrollmentService();
// *** Call the actual CreateEnrolment method on the service
EnrolmentInterface_CreateEnrolment_Output output = client.CreateEnrolment(input);
return output;
}
catch (Exception ex)
{
this.SetError(ex.Message);
}
return null;
}
Works but it's ugly that this has to happen for each of the service methods (especially since each method has different message objects - yuk).
Incidentally it's the 0 or 1 min/maxoccurs that trigger this behavior in the WSDL and it's applied apparently to any value type. It doesn't apply to string values since strings can be null.
Other Posts you might also like