WS SoapException.Message
От: trolik Россия  
Дата: 06.05.04 12:33
Оценка:
Напишу сюда сначала может кто с веб-сервисами работал...

Мне нужно вернуть клиенту сообщение об ошибке (например, "Error"), но возвращается задекорированное сообщение такого вида
xx.WS.HpSoapException: Error
   at xxxxxx.Authenticate(String login, String password, String passwordHash, String ipAddress) in c:\inetpub\xx.ru\xx.asmx.cs:line 77


HpSoapException наследуется от SoapException и override-ит свойство Message... я думал это поможет, оказалось что нет Видимо сообщение об ошибке дополняет остальной информацией серда исполнения... что можно сделать?
Re: WS SoapException.Message
От: PawnHunter  
Дата: 06.05.04 22:09
Оценка:
Здравствуйте, trolik, Вы писали:

T>HpSoapException наследуется от SoapException и override-ит свойство Message... я думал это поможет, оказалось что нет Видимо сообщение об ошибке дополняет остальной информацией серда исполнения... что можно сделать?


Я написал Soap Extension, подключаемый и к серверу и к клиенту.
На сервере: если есть исключение, то оно сериализуется и добавляется к сообщению (прямо в FAULT добавляю узел).
На клиенте: если есть исключение, оно десериализуется и выбрасывается клиенту.
Для работы со стандартными исключениями ничего не нужно — только подключить этот Extension. Для своих нужно еще кое-что сделать.
Если такой подход интересен, могу код кинуть.
Re[2]: WS SoapException.Message
От: trolik Россия  
Дата: 07.05.04 10:08
Оценка:
Здравствуйте, PawnHunter, Вы писали:

PH>Здравствуйте, trolik, Вы писали:


PH>Я написал Soap Extension, подключаемый и к серверу и к клиенту.

PH>На сервере: если есть исключение, то оно сериализуется и добавляется к сообщению (прямо в FAULT добавляю узел).
PH>На клиенте: если есть исключение, оно десериализуется и выбрасывается клиенту.
PH>Для работы со стандартными исключениями ничего не нужно — только подключить этот Extension. Для своих нужно еще кое-что сделать.
PH>Если такой подход интересен, могу код кинуть.
Если честно — с Soap Extensions еще не разбирался, хотя в книжке глава есть.
Но дело в том что веб сервисом будет пользоваться не только мое ASP.NET приложение, но и сторонние клиенты и на их стороне я ничего сделать не могу.

Я всегда в случае ощибки бросаю SoapException, вернее мой класс, наследуемый от него. Клиентам нужно только сообщение об ошибке, например чтобы показать в ASP.NET приложение, а сейчас .NET сует туда кучу другой информации... мне это не надо...
Если расширения могут помочь напиши мне об этом — я все что нужно прочту
Re[3]: WS SoapException.Message
От: PawnHunter  
Дата: 07.05.04 11:04
Оценка:
Здравствуйте, trolik, Вы писали:


T>Я всегда в случае ощибки бросаю SoapException, вернее мой класс, наследуемый от него. Клиентам нужно только сообщение об ошибке, например чтобы показать в ASP.NET приложение, а сейчас .NET сует туда кучу другой информации... мне это не надо...

T>Если расширения могут помочь напиши мне об этом — я все что нужно прочту

Тебе нужно сделать вот, что. На сервере перед отправкой сообщения клиенту проверяешь, было ли исключение (не обязательно SoapException, хотя можешь проверять и все остальное пропускать). Если было исключение, то берешь у него свойство Message и записываешь в soap-сообщение вместо того, что там находится сейчас.

На .Net-клиентах у тебя всегда будет ловиться SoapException, независимо от того, что действительно было выброшено на сервере. Но Message у него теперь будет "правильным". Сторонние клиенты, тоже это поймут (я так думаю.

Подключаешь это расширение к серверу и все.
public class SoapExceptionExtension: SoapExtension
{
    private Stream    _inputStream;
    private Stream    _outputStream;

    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute) 
    {
        // sent to Initialize when configured using attribute
        return typeof(SoapExceptionExtension);
    }

    public override object GetInitializer(Type WebServiceType)
    {
        // sent to Initialize when configured using configuration file
        return typeof(SoapExceptionExtension);
    }

    public override void Initialize(Object initializer) 
    {
        return;
    }
    
    public override Stream ChainStream(Stream stream) 
    {
        _outputStream = stream;
        _inputStream = new MemoryStream();
        return _inputStream;
    }
    
    public override void ProcessMessage(System.Web.Services.Protocols.SoapMessage message) 
    {
        if (message is SoapServerMessage && message.Stage == SoapMessageStage.AfterSerialize)
        {
            // на сервере возникло исключение (message.Exception.InnerException)
            // нужно заменить содержимое элемента "soap:Envelope/soap:Body/soap:Fault/faultstring"
            // в soap-сообщении на значение message.Exception.InnerException.Message
            if (message.Exception.InnerException != null)
            {
                Int64 position = _inputStream.Position;
                _inputStream.Position = 0;

                XmlDocument soapMessageXml = new XmlDocument();
                soapMessageXml.Load(_inputStream);

                XmlNamespaceManager xnm = new XmlNamespaceManager(soapMessageXml.NameTable);
                xnm.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");

                XmlNode soapFaultStringNode = soapMessageXml.SelectSingleNode("/soap:Envelope/soap:Body/soap:Fault/faultstring", xnm);
                if (soapFaultStringNode != null)
                    soapFaultStringNode.InnerText = message.Exception.InnerException.Message;

                soapMessageXml.Save(_outputStream);
                _inputStream.Position = position;
            }
            else
            {
                CopyStream(_inputStream, _outputStream);
            }
        }        
    }
    
    private void CopyStream(Stream sourceStream, Stream destinationStream) 
    {
        Int64 sourcePosition = 0;    
        Int64 destinationPosition = 0;

        if ( sourceStream.CanSeek )
        {
            sourcePosition = sourceStream.Position;
            sourceStream.Position = 0;
        }
        if ( destinationStream.CanSeek )
        {
            destinationPosition = destinationStream.Position;
            destinationStream.Position = 0;
        }
        
        TextReader reader = new StreamReader(sourceStream);
        TextWriter writer = new StreamWriter(destinationStream);
        
        writer.WriteLine(reader.ReadToEnd());
        writer.Flush();
        
        if ( sourceStream.CanSeek )
            sourceStream.Position = sourcePosition;
        
        if(destinationStream.CanSeek)
            destinationStream.Position = destinationPosition;
    }
}


Можешь здесь посмотреть: Using SOAP Extensions in ASP.NET
В "Deploying via Web.config" написано, как подключать.
Re[4]: Исправление
От: PawnHunter  
Дата: 07.05.04 12:20
Оценка: 17 (3)
Sorry, запостил непроверенный код.
Несколько строк нужно добавить:

public class SoapExceptionExtension: SoapExtension
{
    private Stream    _inputStream;
    private Stream    _outputStream;
    private bool    _afterDeserialize = false;

    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute) 
    {
        // sent to Initialize when configured using attribute
        return typeof(SoapExceptionExtension);
    }

    public override object GetInitializer(Type WebServiceType)
    {
        // sent to Initialize when configured using configuration file
        return typeof(SoapExceptionExtension);
    }

    public override void Initialize(Object initializer) 
    {
        return;
    }
    
    public override Stream ChainStream(Stream stream) 
    {        
        if (_afterDeserialize)
        {
            _outputStream = stream;
            _inputStream = new MemoryStream();
            return _inputStream;
        }
        else
        {
            return stream;
        }
    }
    
    public override void ProcessMessage(System.Web.Services.Protocols.SoapMessage message) 
    {
        if ( message is SoapServerMessage )
        {
            if (message.Stage == SoapMessageStage.AfterDeserialize)
            {
                this._afterDeserialize = true;
            }
            else if (message.Stage == SoapMessageStage.AfterSerialize)
            {
                // на сервере возникло исключение (message.Exception.InnerException)
                // нужно заменить содержимое элемента "soap:Envelope/soap:Body/soap:Fault/faultstring"
                // в soap-сообщении на значение message.Exception.InnerException.Message
                
                if (message.Exception != null)
                {
                    string exceptionMessage = 
                        message.Exception.InnerException == null ?
                        message.Exception.Message :
                        message.Exception.InnerException.Message;

                    Int64 position = _inputStream.Position;
                    _inputStream.Position = 0;

                    XmlDocument soapMessageXml = new XmlDocument();
                    soapMessageXml.Load(_inputStream);

                    XmlNamespaceManager xnm = new XmlNamespaceManager(soapMessageXml.NameTable);
                    xnm.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");

                    XmlNode soapFaultStringNode = soapMessageXml.SelectSingleNode("/soap:Envelope/soap:Body/soap:Fault/faultstring", xnm);
                    if (soapFaultStringNode != null)
                        soapFaultStringNode.InnerText = exceptionMessage;

                    soapMessageXml.Save(_outputStream);
                    _inputStream.Position = position;
                }
                else
                {
                    CopyStream(_inputStream, _outputStream);
                }
            }    
        }    
    }
    
    private void CopyStream(Stream sourceStream, Stream destinationStream) 
    {
        Int64 sourcePosition = 0;    
        Int64 destinationPosition = 0;

        if ( sourceStream.CanSeek )
        {
            sourcePosition = sourceStream.Position;
            sourceStream.Position = 0;
        }
        if ( destinationStream.CanSeek )
        {
            destinationPosition = destinationStream.Position;
            destinationStream.Position = 0;
        }
        
        TextReader reader = new StreamReader(sourceStream);
        TextWriter writer = new StreamWriter(destinationStream);
        
        writer.WriteLine(reader.ReadToEnd());
        writer.Flush();
        
        if ( sourceStream.CanSeek )
            sourceStream.Position = sourcePosition;
        
        if(destinationStream.CanSeek)
            destinationStream.Position = destinationPosition;
    }
}
Re[5]: Исправление
От: trolik Россия  
Дата: 07.05.04 12:27
Оценка:
Здравствуйте, PawnHunter, Вы писали:

Спасибо! В понедельник попробую
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.