Java Webservice от клиента .NET C # - Пространства имен сбой? - PullRequest
1 голос
/ 01 марта 2011

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

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

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

<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, сообщая, что элемент username не определен.

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

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

Мы пытались часами: (

Спасибо!

1 Ответ

0 голосов
/ 01 марта 2011

У меня были похожие проблемы с доступом к 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
        }
    }
    
...