Веб-сервис Java от клиента .NET С# - сбой в пространствах имен?

Мы создали веб-сервис с помощью Spring-WS и пытаемся получить к нему доступ из клиента С# .NET. служба работает нормально со всеми тестами, которые мы сделали с SoapUI и другими java-клиентами, но зависает в .NET.

Кажется, это проблема с пространствами имен.

Например, этот запрос работает, когда пространство имен объявлено только в теге конверта, и ни один элемент не имеет пространства имен или префикса в нем:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"     xmlns="http://mycompany.org/schemas">
<soapenv:Header/>
<soapenv:Body>
  <authenticationRequest>
    <username>user</username>
    <password>password</password>
</authenticationRequest>
</soapenv:Body>
</soapenv:Envelope>

Однако этот, казалось бы, эквивалентный запрос НЕ работает:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://mycompany.org/schemas">
<soapenv:Header/>
<soapenv:Body>
  <authenticationRequest xmlns="http://mycompany.org/schemas">
    <username>user</username>
    <password>password</password>
</authenticationRequest>
</soapenv:Body>
</soapenv:Envelope>

Обратите внимание, что в этом случае пространство имен снова объявляется в элементе authenticationRequest. Указанная ошибка заключается в том, что запрос не проверяется на соответствие схеме XML, жалуясь на то, что элемент «имя пользователя» не определен.

К сожалению, при добавлении ссылки на службу (а также веб-ссылки) в .NET код, сгенерированный wsdl.exe, всегда создает запрос во втором случае.

Может ли кто-нибудь объяснить, почему эти два фрагмента XML не эквивалентны, и как мы могли бы в клиенте C#...
- удалить объявление второго пространства имен?
- или добавить префикс пространства имен к каждому элементу в запросе?
- или добавить объявление пространства имен без префикса к каждому элементу?

Мы пытались несколько часов :(

Спасибо!


person npintos    schedule 01.03.2011    source источник


Ответы (1)


У меня были аналогичные проблемы с доступом к Java WS из клиента .NET. Я не нашел элегантного решения проблемы, но решил ее, изменив исходящие/входящие сообщения SOAP с помощью SoapExtension:

  1. Реализуйте атрибут SoapExtensionAttribute следующим образом:

    class SoapExtAttribute : SoapExtensionAttribute
    {
        int priority = 0;
    
        public override Type ExtensionType
        {
            get { return typeof(SoapExt); }
        }
    
        public override int Priority
        {
            get
            {
                return priority;
            }
            set
            {
                priority = value;
            }
        }
    }
    
  2. Реализуйте SoapExtension, например:

    class SoapExt : SoapExtension
    {
        private Stream mWireStream = null;
        private Stream mApplicationStream = null;
    
        public override object GetInitializer(Type serviceType)
        {
            return serviceType;
        }
    
        public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
        {
            return (SoapExtAttribute)attr;
        }
    
        public override void Initialize(object initializer)
        {
        }
    
        public override Stream ChainStream(Stream stream)
        {
            mWireStream = stream;
            mApplicationStream = new MemoryStream();
            return mApplicationStream;
        }
    
    
        public override void ProcessMessage(SoapMessage message)
        {
            StreamWriter writer = null;
            bool fIsServer = (message.GetType() == typeof(SoapServerMessage));
            switch (message.Stage)
            {
                case SoapMessageStage.BeforeDeserialize:
                    string resp = new StreamReader(mWireStream).ReadToEnd();
                    StreamWriter w = new StreamWriter(mApplicationStream);
                    w.WriteLine(resp);
                    w.Flush();
                    mApplicationStream.Seek(0, SeekOrigin.Begin);
                    break;
                case SoapMessageStage.AfterSerialize:
                    mApplicationStream.Seek(0, SeekOrigin.Begin);
                    string reqXml = new StreamReader(mApplicationStream).ReadToEnd();
    
                    XmlDocument doc = new XmlDocument();
                    doc.LoadXml(reqXml);
    
                    Modify(doc);
    
                    reqXml = doc.InnerXml;
    
                    mApplicationStream.Seek(0, SeekOrigin.Begin);
                    writer = new StreamWriter(mWireStream);
                    writer.WriteLine(reqXml);
                    writer.Flush();
    
                    XmlDocument d = new XmlDocument();
                    d.LoadXml(reqXml);
                    ServiceManager.RequestSoap = d.LastChild.OuterXml;
                    break;
            }
        }
    
        private void Modify(XmlDocument doc)
        {
            // Change the doc in whatever way you want, e.g. remove/add the prefixes
        }
    }
    
person nogola    schedule 01.03.2011
comment
привет, спасибо за такой развернутый ответ! Но, к сожалению, я не очень разбираюсь в C#/.NET/webServices. Не могли бы вы объяснить, куда поместить этот код в классе, сгенерированном после добавления ссылки на службу? - person npintos; 01.03.2011
comment
наконец нам удалось заставить его работать. Чтобы перехватить запрос мыла, вам просто нужно добавить: [SoapExt] поверх объявления веб-метода. - person npintos; 01.03.2011
comment
может ли кто-нибудь сказать мне, где вам удалось найти правильную ссылку для ServiceManager.RequestSoap - person hal9000; 03.05.2011
comment
Я считаю, что ServiceManager.RequestSoap - это просто поле, в котором он сохраняет XML для какой-то другой цели. Это не относится к решению. В этот момент XML изменен и записан в сеть, и сброшен... - person Emyr; 07.11.2013