1

I generated C# classes from .wsdl file and it works. But I have following issue. Service formats xsd:date types in response incorrect. Example:

<date xsi:type="xsd:date">2016-01-27 14:20:30</date>

But it should be one of these:

<date xsi:type="xsd:date">2016-01-27</date>  
<date xsi:type="xsd:dateTime">2016-01-27T14:20:30</date>

And because of that I get exception

Unhandled Exception: System.ServiceModel.CommunicationException: Error in deserializing body of reply message for operation 'createVacature'. ---> System.InvalidOperationException: There is an error in XML document (2, 646). ---> System.FormatException: String was not recognized as a valid DateTime.

How can I override date parsing? Or any other way to fix it? Implementing all that manually without svcutil.exe would be overkill.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
ZyXEL
  • 163
  • 1
  • 12
  • probably, it's error on server side, thay promised date in wsdl, but generated shit. If you can't change nothing on server side, your way - find this field in generated code (will be something like `public DateTime date{ get{} set{}}`) and replace type DateTime with type string. Your client will accept responses, but you have to convert this 'nice' ODBC canonical format for date into DateTime (of course, if you really need the date) – vitalygolub Jan 27 '16 at 16:35
  • That's the first thing I tried, but it anyway is parsed as DateTime. I found interesting solution to intercept xml before parsing and fix date format manually, still working on it, looks promising. – ZyXEL Jan 28 '16 at 08:19

1 Answers1

2

Here is my solution. I intercept service response before parsing and manually edit it.

Here is date fixing functionality:

public class MessageDateFixer : IClientMessageInspector
{
    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        return null;
    }

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        XmlDocument document = new XmlDocument();
        MemoryStream memoryStream = new MemoryStream();
        XmlWriter xmlWriter = XmlWriter.Create(memoryStream);
        reply.WriteMessage(xmlWriter);
        xmlWriter.Flush();
        memoryStream.Position = 0;
        document.Load(memoryStream);

        FixMessage(document);

        memoryStream.SetLength(0);
        xmlWriter = XmlWriter.Create(memoryStream);
        document.WriteTo(xmlWriter);
        xmlWriter.Flush();
        memoryStream.Position = 0;
        XmlReader xmlReader = XmlReader.Create(memoryStream);
        reply = Message.CreateMessage(xmlReader, int.MaxValue, reply.Version);
    }

    private static void FixMessage(XmlDocument document)
    {
        FixAllNodes(document.ChildNodes);
    }

    private static void FixAllNodes(XmlNodeList list)
    {
        foreach (XmlNode node in list)
        {
            FixNode(node);
        }
    }

    private static void FixNode(XmlNode node)
    {
        if (node.Attributes != null &&
            node.Attributes["xsi:type"] != null)
        {
            if (node.Attributes["xsi:type"].Value == "xsd:date")
            {
                node.Attributes["xsi:type"].Value = "xsd:dateTime";
                node.InnerXml = node.InnerXml.Replace(" ", "T");
            }
        }

        FixAllNodes(node.ChildNodes);
    }
}

Here is auxiliary class:

public class DateFixerBehavior : IEndpointBehavior
{
    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(new MessageDateFixer());
    }

    public void Validate(ServiceEndpoint endpoint)
    {

    }

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {

    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {

    }
}

Here is usage:

PosterToolClient poster = new PosterToolClient();
poster.Endpoint.Behaviors.Add(new DateFixerBehavior());
ZyXEL
  • 163
  • 1
  • 12