Веб-служба ESTES ShipmentTracking v1.1, ошибка в десериализации тела ответного сообщения для операции 'shipmentTracking' - PullRequest
0 голосов
/ 13 июня 2019

Я пытаюсь разработать простое приложение Windows Forms для запроса информации об отслеживании из последней версии веб-сервиса ESTES ShipmentTracking v1.1.Когда я выполняю запрос, моя программа выдает System.ServiceModel.CommunicationException

. Я использую приложение Windows Forms для Visual Studio 2019 и .NET 4.6.2 C #.Я настроил Connected Service, используя процедуру Add Service Reference, и использую пространство имен ESTES_Track.Вот мой основной код:

ESTES_Track.EstesShipmentTracking_PortTypeClient trackClient = new EstesShipmentTracking_PortTypeClient();
trackClient.ClientCredentials.UserName.UserName = "MYUSERNAME";
trackClient.ClientCredentials.UserName.Password = "MYPASSWORD";
ESTES_Track.search trackSearch = new ESTES_Track.search();
trackSearch.requestID = "TRACK" + DateTime.Now.Ticks.ToString();
trackSearch.pro = "1710394802";
ESTES_Track.shipmentTrackingRequest trackRequest = new shipmentTrackingRequest(trackSearch);
ESTES_Track.shipmentTrackingResponse trackResponse = trackClient.shipmentTracking(trackRequest);

Исключение связи:

Error in deserializing body of reply message for operation 'shipmentTracking'
There is an error in XML document (1, 575)
   at System.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader reader, MessageVersion version, XmlSerializer serializer, MessagePartDescription returnPart, MessagePartDescriptionCollection bodyParts, Object[] parameters, Boolean isRequest)
   at System.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader reader, MessageVersion version, String action, MessageDescription messageDescription, Object[] parameters, Boolean isRequest)
   at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest)
   at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeReply(Message message, Object[] parameters)
   at System.ServiceModel.Dispatcher.ProxyOperationRuntime.AfterReply(ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at EstesTests.ESTES_Track.EstesShipmentTracking_PortType.shipmentTracking(shipmentTrackingRequest request)
   at EstesTests.ESTES_Track.EstesShipmentTracking_PortTypeClient.shipmentTracking(shipmentTrackingRequest request) in C:\tests\EstesTests\Connected Services\ESTES_Track\Reference.cs:line 1394
   at EstesTests.Program.TrackTest() in C:\tests\EstesTests\Program.cs:line 49

- = - = - = - edit - = - = - = - Я могу успешно обработать запрос иполучить действительный ответ, используя SoapUI.Это заставляет меня поверить, что моя проблема связана с моим проектом Visual Studio.

Мой файл App.config выглядит следующим образом:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
    </startup>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Binder">
                  <security mode="Transport">
                    <transport clientCredentialType="Basic"></transport>
                  </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="https://api.estes-express.com:443/ws/estesrtshipmenttracking.base.ws.provider.soapws:EstesShipmentTracking/estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Port"
                binding="basicHttpBinding" bindingConfiguration="estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Binder"
                contract="ESTES_Track.EstesShipmentTracking_PortType" name="estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Port" />
        </client>
    </system.serviceModel>
</configuration>

- = - = - = - edit - = -= - = - Причина, по которой я явно обозначил это как «ESTES ShipmentTracking v1.1», заключается в том, что я вполне уверен, что проблемы, с которыми я сталкиваюсь, вероятно, специфичны для этого конкретного веб-сервиса.Если у кого-то уже есть пример рабочего кода для использования этого веб-сервиса, это может включать решение моей проблемы.Кроме того, я уверен, что любой другой, пытающийся разработать клиент доставки для ESTES, столкнется с этой проблемой.сообщения не полностью соответствуют опубликованной схеме WSDL v1.1 и что исключения десериализации являются специфическими для данной версии реализации веб-сервиса.У меня не было этой проблемы с предыдущей версией v1.0.

1 Ответ

1 голос
/ 20 июня 2019

Я столкнулся с той же проблемой сегодня и сузил ее до пары проблем:

  • EventTimeStamp отсутствует двоеточие в части часового пояса
  • Пустые поля отсутствуют xsi: nil

Я написал в техподдержку, но тем временем смог заставить его работать, манипулируя ответом с помощью специального инспектора сообщений, как описано здесь https://blogs.msdn.microsoft.com/dsnotes/2015/04/14/wcf-simple-way-to-modify-serialized-response/.

Вы можете добавитьэто для вашего клиента вот так:

trackClient.Endpoint.Behaviors.Add(new EstesTrackingEndpointBehavior());

Надеюсь, они смогут решить эту проблему со своей стороны.Если возникают другие проблемы, вы можете добавить дополнительные изменения в ответ в AfterReceiveReply:

using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Xml;

namespace EstesWebService {
    public class EstesTrackingMessageInspector : IClientMessageInspector {
        public void AfterReceiveReply(ref Message reply, object correlationState) {
            var doc = new XmlDocument();
            var ms = new MemoryStream(); 
            var writer = XmlWriter.Create(ms);
            reply.WriteMessage(writer);
            writer.Flush();
            ms.Position = 0;
            doc.Load(ms);

            //fix the XML
            addNil(doc.SelectNodes(".//shipments"));
            foreach (XmlNode node in doc.SelectNodes(".//eventTimeStamp"))
                fixDateTimeFormat(node);

            ms.SetLength(0);
            writer = XmlWriter.Create(ms);
            doc.WriteTo(writer);
            writer.Flush();
            ms.Position = 0;
            var reader = XmlReader.Create(ms);
            reply = Message.CreateMessage(reader, int.MaxValue, reply.Version);
        }

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

        private void addNil(XmlNodeList nodes) {
            foreach (XmlNode node in nodes) {
                if (node.HasChildNodes)
                    addNil(node.ChildNodes);
                else if (string.IsNullOrWhiteSpace(node.InnerText) && node.Attributes != null && node.Attributes.GetNamedItem("xsi:nil") == null) {
                    var attr = node.OwnerDocument.CreateAttribute("xsi", "nil", "http://www.w3.org/2001/XMLSchema-instance");
                    attr.Value = "true";
                    node.Attributes.SetNamedItem(attr);
                }
            }
        }

        private void fixDateTimeFormat(XmlNode node) {
            if (node != null && !string.IsNullOrWhiteSpace(node.InnerText)) {
                DateTimeOffset dt;
                if (DateTimeOffset.TryParse(node.InnerText.Trim(), out dt))
                    node.InnerText = dt.ToString("O");
            }
        }

    }

    public class EstesTrackingEndpointBehavior : IEndpointBehavior {
        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) {
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) {
            clientRuntime.MessageInspectors.Add(new EstesTrackingMessageInspector());
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) {
        }

        public void Validate(ServiceEndpoint endpoint) {
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...