Change culture when deserializing WCF service

隐身守侯 提交于 2019-12-04 19:05:00

Have you tried using a custom IClientMessageFormatter.DeserializeReply() implementation? WCF is stuffed to the gills with extensibility points, so it's often hard to know which one to pick, but DeserializeReply looks like the right tool for this job.

Take a look at this blog post-- sorry its original site is offline so pointing to Internet Archive version which looks like a similar thing to what you're trying to do: using a WCF client to call a non-WCF web service, and to do specialized processing of the response to account for non-WCF-like behavior on the server.

Here's a code excerpt from that blog:

public object DeserializeReply(Message message, object[] parameters)
{
    object helperInstance = Activator.CreateInstance(_return);

    //we have special condition where service sets Http response code to 403 that signals that an error has occured 
    KeyValuePair<string,object> serviceErrorProperty = message.Properties.FirstOrDefault(p => p.Key == ResponseErrorKey);
    if (serviceErrorProperty.Key != null)
    {
        //we have an error message
        IResponseErrorProvider responseErrorProvider = helperInstance as IResponseErrorProvider;
        if (responseErrorProvider != null)
        {
            //unpack the error payload from message and assign to the object
            ResponseError payload = message.GetBody<ResponseError>();
            responseErrorProvider.ServiceError = payload;

            //return fixed null type with error attached to it
            return helperInstance;
        }
    }

    //another message we might get is <nil-classes type="array"/> for empty arrays.
    XmlDictionaryReader xdr = message.GetReaderAtBodyContents();
    xdr.MoveToContent();

    if (xdr.Name == NullMessage)
    {
        return helperInstance; //standin for the null value
    }

    return _formatter.DeserializeReply(message, parameters);
}

public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
    return _formatter.SerializeRequest(messageVersion, parameters);
}

You could attach a culture initializer to a behaviour which you then add to an endpoint. This would set the culture on the thread deserializing the response, the field should therefore, be deserialized correctly.

For a code example of this, have a look at this link:

http://blogs.msdn.com/drnick/archive/2008/02/26/using-call-context-initializers-for-culture.aspx

I would be very surprised if the culture is really the problem. XML spec says that decimals are using the dot as separator, and the (de)serializer knows this. Can you trace the message and see what's in at position 941? (By the way: I like SoapUI for such things, besides WCF tracing) When it comes to decimals, maybe the different precision might be a problem: maybe the Java service puts more 666666666666 before the trailing 7 in case of two thirds that the .net decimal can handle?

And there is a second option: the decimal is not really a decimal (again: tracing the message would be very enlighting). I found this link which laments a little bit about the amazon services, that might put the unit into the decimal value (by the way: WTF!?). However, there is a nice description on how to interact with the raw message before passing it to the deserialization using the IClientMessageInspector interface. If such a strange case is your problem you could either force the service provider to comply with his own contract or do such a trick (if the provider is outside your sphere of control and says "this is by design").

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!