Напишу сюда сначала может кто с веб-сервисами работал...
Мне нужно вернуть клиенту сообщение об ошибке (например, "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... я думал это поможет, оказалось что нет

Видимо сообщение об ошибке дополняет остальной информацией серда исполнения... что можно сделать?
Здравствуйте, trolik, Вы писали:
T>HpSoapException наследуется от SoapException и override-ит свойство Message... я думал это поможет, оказалось что нет
Видимо сообщение об ошибке дополняет остальной информацией серда исполнения... что можно сделать?
Я написал Soap Extension, подключаемый и к серверу и к клиенту.
На сервере: если есть исключение, то оно сериализуется и добавляется к сообщению (прямо в FAULT добавляю узел).
На клиенте: если есть исключение, оно десериализуется и выбрасывается клиенту.
Для работы со стандартными исключениями ничего не нужно — только подключить этот Extension. Для своих нужно еще кое-что сделать.
Если такой подход интересен, могу код кинуть.
Здравствуйте, PawnHunter, Вы писали:
PH>Здравствуйте, trolik, Вы писали:
PH>Я написал Soap Extension, подключаемый и к серверу и к клиенту.
PH>На сервере: если есть исключение, то оно сериализуется и добавляется к сообщению (прямо в FAULT добавляю узел).
PH>На клиенте: если есть исключение, оно десериализуется и выбрасывается клиенту.
PH>Для работы со стандартными исключениями ничего не нужно — только подключить этот Extension. Для своих нужно еще кое-что сделать.
PH>Если такой подход интересен, могу код кинуть.
Если честно — с Soap Extensions еще не разбирался, хотя в книжке глава есть.
Но дело в том что веб сервисом будет пользоваться не только мое ASP.NET приложение, но и сторонние клиенты и на их стороне я ничего сделать не могу.
Я всегда в случае ощибки бросаю SoapException, вернее мой класс, наследуемый от него. Клиентам нужно только сообщение об ошибке, например чтобы показать в ASP.NET приложение, а сейчас .NET сует туда кучу другой информации... мне это не надо...
Если расширения могут помочь напиши мне об этом — я все что нужно прочту
Здравствуйте, 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" написано, как подключать.
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;
}
}
Здравствуйте, PawnHunter, Вы писали:
Спасибо! В понедельник попробую