Search code examples
wcfpowershellnew-webserviceproxy

Powershell WCF service DateTime property always DateTime.Min (01.01.0001)


i've detected a strange behavior calling a WCF Service from a Powershell script. Using the command 'New-WebServiceProxy' from Powershell 2.0 get's you the abillity to send requests to a Webservice from a PS script. But i got some problems with System.DateTime objects on the service side, the value on the server side is always DateTime.Min.

So i created a small test service an script and i can reproduce this error. I used a 'standard' WCF-Project from VS2010 and extedended the 'DataContract' Class with a DateTime Property:

[DataContract]
public class CompositeType
{
    bool boolValue = true;
    string stringValue = "Hello ";

    [DataMember]
    public bool BoolValue
    {
        get { return boolValue; }
        set { boolValue = value; }
    }

    [DataMember]
    public string StringValue
    {
        get { return stringValue; }
        set { stringValue = value; }
    }

    [DataMember]
    public DateTime Datum { get; set; }
} 

Powershell script to call the service:

cls 
$serv = New-WebServiceProxy  -uri 'http://localhost:50176/TestService.svc?wsdl' -     Namespace wt
$data = [wt.CompositeType](New-Object wt.CompositeType)
$data.StringValue = "abcd"
$data.BoolValue = $true
$data.Datum = Get-Date
$serv.GetDataUsingDataContract($data)

If needed, i can send you a dropbox link for the zipped project.

Regards Uwe


Solution

  • I've never used powershell before but thought I'd take a long overdue look at it for this question!

    The proxy object $data can have a date property set but, despite what your code looks like its doing, $data isn't the real object, just an XML proxy of it.

    If you enter command "$data" you'll see what looks like an XmlSerialized version of the object (has xxSpecified properties for the bool and DateTime). It does reflect changes made by e.g. "$data.Datum = Get-Date".

    The proxy is deserialised back to an instance of MyCompositeType when you call GetUsingDataContract (as its passed as a parameter and sent using XML) which you can see by putting breakpoints on the property get/setters prior to calling it.

    As part of this deserialization, only the StringValue makes it which is because the Xml serialization for the other properties will only include values where "xxxSpecified" is true.

    If you set the "xxxSpecified" properties in the proxy they will serialize back correctly.

    But the best fix is to change their DataMember attribute to:

    [DataMember(IsRequired=true)]
    

    Which should just work with the code you've got.