2009-06-05 1 views
0

В последнее время мы были видим исключение, как это в нашем .NET (.asmx) WebServices:Как отлаживать искаженные запросы на мыло?

System.Web.Services.Protocols.SoapException: Server was unable to read request. ---> System.InvalidOperationException: There is an error in XML document (868, -3932). ---> System.Xml.XmlException: '.', hexadecimal value 0x00, is an invalid character. Line 868, position -3932. 
    at System.Xml.XmlTextReaderImpl.Throw(Exception e) 
    at System.Xml.XmlTextReaderImpl.Throw(String res, String[] args) 
    at System.Xml.XmlTextReaderImpl.Throw(Int32 pos, String res, String[] args) 
    at System.Xml.XmlTextReaderImpl.ThrowInvalidChar(Int32 pos, Char invChar) 
    at System.Xml.XmlTextReaderImpl.ParseNumericCharRefInline(Int32 startPos, Boolean expand, BufferBuilder internalSubsetBuilder, Int32& charCount, EntityType& entityType) 
    at System.Xml.XmlTextReaderImpl.ParseText(Int32& startPos, Int32& endPos, Int32& outOrChars) 
    at System.Xml.XmlTextReaderImpl.ParseText() 
    at System.Xml.XmlTextReaderImpl.ParseElementContent() 
    at System.Xml.XmlTextReaderImpl.Read() 
    at System.Xml.XmlTextReader.Read() 
    at System.Web.Services.Protocols.SoapServerProtocol.SoapEnvelopeReader.Read() 
    at System.Xml.XmlReader.ReadElementString() 
    at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read14_SendErrlog() 
    at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer12.Deserialize(XmlSerializationReader reader) 
    at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events) 
    --- End of inner exception stack trace --- 
    at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events) 
    at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle) 
    at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters() 
    --- End of inner exception stack trace --- 
    at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters() 
    at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest() 

Как я могу отладить это исключение? Это исключение сообщается нам из фильтра SOAP, который ищет исключения в сообщении. Stage = SoapMessageStage.AfterSerialize.

Есть ли какой-либо способ получить первоначальный запрос на мыло? Как получить недопустимый символ в строке 868, столбец -3932? Как может быть отрицательный столбец 3932?

ответ

3

Это одно из раздражающих факторов, связанных с подходом веб-служб Microsoft - если запрос не может быть десериализован в объекты в вашей сигнатуре веб-метода, тогда пользователь службы получает загадочное сообщение. И в довершение всего, запрос никогда не попадает в ваш веб-сервис, потому что его нельзя десериализовать, чтобы вы не могли обработать ошибку изящно.

Что я хотел бы сделать, чтобы помочь с этими типами проблем, является создание нового SoapExtension, которое просто позволяет выводить необработанный XML в удобное для вас место назначения (файл или трассировка, которые будут прочитаны DebugView или что-то еще, что вы как). Код будет идти на этапе BeforeDeserialize. Вы можете включить SoapExtension через web.config в случае, если вы хотите изучить одну из этих проблем. Недостатком использования web.config для добавления SoapExtension является то, что он будет активен для всего веб-приложения. Вы можете добавить дополнительную настраиваемую конфигурацию, которая позволит вашей службе регистрировать информацию только для определенной конечной точки или определенного веб-метода, если вы хотите.

Обычно, просматривая входящий XML, вы можете видеть, в чем проблема. Если нет, вы можете попытаться вручную запустить захваченный XML через небольшую программу, которая вызывает сериализатор XML и посмотреть, сможете ли вы узнать, что происходит. Другим полезным инструментом является Web Service Studio 2, который является тестовым жгутом, который позволяет вводить данные и вызывать вашу службу (а также отправлять любые XML-файлы).

С точки зрения вашей конкретной проблемы, вот мой вопрос. Похоже, что символ символа ASCII null получает кодировку и отправляется на вашу службу, которая недействительна в соответствии с спецификацией XML. Простой ответ заключается не в том, чтобы отправить этот символ. Но кто посылает этого персонажа? Это клиент .NET? У вас есть контроль над клиентом?Если вам нужно обойти чужую ошибку, вам может потребоваться заменить оскорбительный символ (ы) другим символом (возможно, пустой строкой).

+0

Наше приложение является клиентом, и оно просто отправляет некоторый текст с текстом xml-literal (& , <, > и т. П.). В этом случае никогда не должно быть никаких нулей. Это исключение даже происходит по запросу мыла без параметров. Клиент использует «Web Reference» для доступа к серверу, поэтому мы даже не создаем SOAP вручную. Я думаю, что вы правы, мне просто нужно захватить все SOAP-запросы. Наш NOC будет любить меня, когда я заполню папку журналов ;-) –

2

Вы должны иметь возможность получить исходное сообщение, используя другое SoapExtension. На самом деле одно и то же расширение, вероятно, можно было бы изменить, чтобы сделать копию ввода, и отбросить его, если нет исключения. Тогда исходный вход будет доступен вам, если возникло исключение.

Вы также можете использовать внешний инструмент, такой как Fiddler, для просмотра того, что вам отправлено.

+0

Итак, в основном скопируйте его в сообщении. Stage = SoapMessageStage.BeforeDeserialize? Могу ли я гарантировать, что первый AfterDeserialize для сообщения A поступит сразу после A BeforeDeserialize? –

+0

Я также хотел бы узнать ответ на вопрос Боб Кинга; это был подход, который я придумал сам, и пошел писать SoapExtension, и понял, что не могу придумать способ сделать это без проблем. :( – Grank

+0

Извините, я не ответил. Ответ: если документация не дает гарантии, тогда нет никакой гарантии. –

0

FYI: SoapException.Message намеренно оставлено неопределенным, чтобы предотвратить чрезмерную информацию, которая потенциально может быть использована для использования системы.

Для вашего конкретного случая я бы взял совет Джона и установил Fiddler для мониторинга фактического HTTP-трафика и просмотра сообщения на проводе.

Часть вашего исключения, которая выпрыгивает на меня, представляет собой «шестнадцатеричное значение 0x00, является недопустимым символом», но, как вы упомянули, номер строки, на которую он указывает, является койкой - так что это ничего конкретного.

Какие параметры вы передаете услуге? Выполняете ли вы какую-либо пользовательскую кодировку с расширением SOAP? Добавляются ли какие-либо дополнительные заголовки SOAP?