Как принять SoapException на стороне клиента

Я получал ужасный тип содержимого ответа «клиент нашел ответ» «text/html», но ожидал ошибку «test/xml», но после некоторого поиска в Google я нашел этот пост о том, как вернуть исключение SoapException.

Итак, я пошел дальше и реализовал это, но теперь я все еще получаю ту же ошибку. Есть ли изменения, которые мне нужно внести на стороне клиента, чтобы иметь возможность принимать SoapException (я бы так не думал, все просто наследуется от Exception, верно?)

Почему я все еще получаю этот ужасный ответ на стороне клиента?

    [WebMethod]
    [SoapHeader("authenticationHeader")]
    [WebServiceAuthentication(AuthenticationRequired = false)]
    public DataSet GetConversionErrors()
    {
        try
        {
            return Components.PWD.GetConversionErrors();
        }
        catch (Exception ex)
        {
            PublishingManager.Publish(ex, HttpContext.Current.User.Identity.Name);
            throw Components.SoapException.GenerateSoapException(ex, Context);
        }
    }

Изменить: я знаю, что исключение в этом блоке catch — это именно то, что мне нужно увидеть, но я все еще получаю исключение System.InvalidOperationException на стороне клиента.

Edit2: я подключаюсь к веб-сервисам через WebReference (вызывая файл *.asmx), если это помогает/имеет значение.

Edit3: вот что записывается в наш журнал исключений на стороне сервера (в вызове PublishingManager.Publish()). Я думал, что это должно быть то, что возвращается клиенту...

Exception Details:
Exception Type: System.Exception
Message: Test the text/html text/xml message. 
Method: PWD.Components.PWD.GetConversionErrors 
Username: xxxxxx Created 5/22/2012 4:20:53 PM 
Application: xxxx Application Identity: NT AUTHORITY\IUSR 
Source: xxxx Severity 2 
Machine: xxxxxxxxx IP Address 127.0.0.1 
AppDomain /LM/W3SVC/1/ROOT-1-129821937733610609 
Stack Trace    at PWD.Components.PWD.GetConversionErrors() in C:\Vault\Development-New\Web\Main_Logging\PWD\Components\PWD.cs:line 73 
   at PWD.PWD.GetConversionErrors() in C:\Vault\Development-New\Web\Main_Logging\PWD\PWD.asmx.cs:line 44 
Additional Information:
  +System.Exception: 
    Message: Test the text/html text/xml message. 
    Data: System.Collections.ListDictionaryInternal 
    InnerException:  
    TargetSite: System.Data.DataSet GetConversionErrors() 
    StackTrace:    at PWD.Components.PWD.GetConversionErrors() in C:\Vault\Development-New\Web\Main_Logging\PWD\Components\PWD.cs:line 73 
   at PWD.PWD.GetConversionErrors() in C:\Vault\Development-New\Web\Main_Logging\PWD\PWD.asmx.cs:line 44 
    HelpLink:  
    Source: xxxx 
     UserName: xxxxxxx 
     TypeName: PublishingManager 
     MachineName: xxxxxxxxx 
     TimeStamp: 5/22/2012 4:20:54 PM 
     FullName: Services.Publishing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=null 
     AppDomainName: /LM/W3SVC/1/ROOT-1-129821937733610609 
     ThreadIdentity:  
     WindowsIdentity: NT AUTHORITY\IUSR 
     Severity: 2 
     MachineIPAddress: 127.0.0.1 

Edit3: Просто хочу добавить этот дополнительный фрагмент кода, чтобы люди увидели, как я тестирую эти исключения (и, возможно, это неправильный способ тестирования...). В моем первом фрагменте кода у меня есть вызов внутри блока try для «return Components.PWD.GetConversionErrors();», вот этот метод:

    public static DataSet GetConversionErrors()
    {
        DB db = new DB();

        try
        {
            //return db.ExecuteDataset(Configuration.GenericConfig.AppConnectionString, CommandType.Text, spGetConversionErrors);
            throw new Exception("Test the text/html text/xml message.");
        }
        catch
        {
            throw;
        }
    }

Как видите, я закомментировал вызов и просто добавил свою собственную строку, которая каждый раз будет вызывать исключение для целей тестирования...

Edit4: @gbvb Вот новый метод:

    [WebMethod]
    [SoapHeader("authenticationHeader")]
    [WebServiceAuthentication(AuthenticationRequired = false)]
    public DataSet GetConversionErrors()
    {
        try
        {
            return Components.PWD.GetConversionErrors();
        }
        catch (Exception ex)
        {
            //PublishingManager.Publish(ex, HttpContext.Current.User.Identity.Name);
            //throw Components.SoapException.GenerateSoapException(ex, Context);

            System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
            System.Xml.XmlNode detailNode = xmlDoc.CreateNode(System.Xml.XmlNodeType.Element, System.Web.Services.Protocols.SoapException.DetailElementName.Name, System.Web.Services.Protocols.SoapException.DetailElementName.Namespace);
            detailNode.InnerText = ex.ToString();

            throw new System.Web.Services.Protocols.SoapException(ex.Message, System.Web.Services.Protocols.SoapException.ClientFaultCode, System.Web.HttpContext.Current.Request.Url.AbsoluteUri, detailNode, ex.InnerException);
        }
    }

Edit5: Что видел Fiddler2:

HTTP/1.1 500 Internal Server Error
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Wed, 23 May 2012 19:25:56 GMT
Content-Length: 1208

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<title>500 - Internal server error.</title>
<style type="text/css">
<!--
body{margin:0;font-size:.7em;font-family:Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;}
fieldset{padding:0 15px 10px 15px;} 
h1{font-size:2.4em;margin:0;color:#FFF;}
h2{font-size:1.7em;margin:0;color:#CC0000;} 
h3{font-size:1.2em;margin:10px 0 0 0;color:#000000;} 
#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS", Verdana, sans-serif;color:#FFF;
background-color:#555555;}
#content{margin:0 0 0 2%;position:relative;}
.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}
-->
</style>
</head>
<body>
<div id="header"><h1>Server Error</h1></div>
<div id="content">
 <div class="content-container"><fieldset>
  <h2>500 - Internal server error.</h2>
  <h3>There is a problem with the resource you are looking for, and it cannot be displayed.</h3>
 </fieldset></div>
</div>
</body>
</html>

Если кто-то знает, как красиво отформатировать этот раздел, пожалуйста, сделайте :)


person ganders    schedule 22.05.2012    source источник
comment
Итак, я пошел дальше и реализовал это, но теперь я все еще получаю ту же ошибку, которую я слышал и говорил раньше. Вы уверены, что полностью внедрили свои изменения и развернули их в среде, в которой тестируете?   -  person Josh Stodola    schedule 23.05.2012
comment
Кроме того, очень важно знать, какую версию .NET вы используете.   -  person Josh Stodola    schedule 23.05.2012
comment
Я так думаю, я запускаю веб-сервисы на своем локальном хосте и просто вызываю это. Я могу установить точки останова как на стороне сервера, так и на стороне клиента... но когда он останавливается на стороне клиента, фактическим исключением, возвращаемым с сервера, является InvalidOperationException вместо SoapException.   -  person ganders    schedule 23.05.2012
comment
Мое плохое, работающее на стороне клиента .NET 3.5 и на стороне сервера ASP.NET 2.0.   -  person ganders    schedule 23.05.2012
comment
Вы уверены, что PublishingManager.Publish не вылетит до того, как вы вызовете исключение SoapException?   -  person Josh Stodola    schedule 23.05.2012
comment
Можете ли вы использовать конечные точки GET/POST на веб-страницах, чтобы увидеть, какой HTML возвращается? Вы можете прочитать вывод HTML и посмотреть, на что он жалуется. Иногда из этого можно извлечь информацию.   -  person gbvb    schedule 23.05.2012
comment
Да. Это публикация фактического исключения в нашей таблице журнала исключений (которая, как я убедился, существует), и я могу пройти через этот код и посмотреть, как он попадет в часть throw Components.SoapException....... Я просто прокомментировал эту строку, чтобы подтвердить еще раз, и она по-прежнему дает те же результаты.   -  person ganders    schedule 23.05.2012
comment
@gbvb Разве это не для веб-страниц? Я вызываю веб-сервисы через WinForms.   -  person ganders    schedule 23.05.2012
comment
Это имеет значение? если у вас есть веб-служба, ее можно вызвать напрямую через HTTP GET/POST или, по крайней мере, проверить ответ text/html. В нем должен быть текст, который вы можете прочитать, что может привести вас к тому, какое состояние он видит.   -  person gbvb    schedule 23.05.2012
comment
Что это за атрибут WebServiceAuthentication?   -  person John Saunders    schedule 23.05.2012
comment
Кроме того, как вы потребляете услугу? Добавить ссылку на сервис? Есть ли способ переключиться на WCF? ASMX не поддерживает ошибки.   -  person John Saunders    schedule 23.05.2012
comment
@JohnSaunders, это был настраиваемый процесс аутентификации, но с тех пор они были переключены на AuthenticationRequired = false, поэтому их больше не вызывают ... просто никогда не удаляли атрибут. Я использую веб-сервисы через WebReference (старый стиль .NET 1.1). Переход на WCF был бы серьезной задачей, потому что у нас есть более 100 веб-сервисов на нашем веб-сайте.   -  person ganders    schedule 23.05.2012
comment
В большинстве случаев перейти с ASMX на WCF не так сложно. Клиентскому коду даже не нужно знать о переключении. Кроме того, в этом году будет намного проще переключиться, чем через пять или десять лет, когда никто даже не вспомнит, что такое ASMX раньше. Кроме того, как я уже сказал, ASMX не поддерживает должным образом ошибки.   -  person John Saunders    schedule 23.05.2012
comment
@JohnSaunders это предлагаемый подход к преобразованию? Если да, значит ли это, что мне нужно добавить 100 конечных точек службы в мой файл web.config? Если это так, то мне нужно добавить те же самые 100 конечных точек в мой процесс сборки, чтобы обновить их значения...   -  person ganders    schedule 23.05.2012
comment
Что-то вроде этого, но этому уже несколько лет. В частности, конфигурация службы намного проще в .NET 4.0, поэтому я не уверен, что вам придется добавлять отдельные конечные точки в файл web.config. Если бы вы это сделали, вам, вероятно, нужно было бы указать только URL-адрес каждой конечной точки и немного больше — все остальное было бы по умолчанию. Кроме того, в .NET 4.0 процесс сборки не требует их обновления. Вы должны использовать преобразования web.config.   -  person John Saunders    schedule 24.05.2012
comment
Хорошо, я преобразовал веб-службу/метод, который я тестирую, для использования WCF, и мой код все еще получает исключение text/html вместо исключения мыла. Нужно ли мне преобразовывать ВСЕ веб-методы в моем веб-сервисе в WCF, потому что я преобразовал ТОЛЬКО тот, который тестирую. Я добавил атрибут [ServiceContract(Namespace = blah)] к веб-службе и [OperationContract] к методу, а затем добавил тег ‹system.serviceModel› в свой файл web.config. #расстроенный   -  person ganders    schedule 06.06.2012


Ответы (2)


Итак, я заставил его работать. Вот что я узнал:

При просмотре свойств моего веб-сайта в IIS, а затем при выборе «Модули» появляется запись под названием «CustomErrorModule», которая пытается обработать ошибки, выдаваемые веб-сайтом/веб-службой.

Исправление состоит в том, чтобы либо удалить эту запись «CustomErrorModule», либо обновить мой файл конфигурации из:

<httpErrors errorMode="Custom" existingResponse="Replace">

to:

<httpErrors errorMode="Custom" existingResponse="Auto">

Спасибо всем за помощь, это направило меня в правильном направлении. (Кстати, я обновляю файл конфигурации, поэтому мне не нужно возиться с модулями)

Кроме того, вот ссылка, объясняющая эту ситуацию.

person ganders    schedule 13.06.2012

Просто для хихиканья, можете ли вы попробовать явно генерировать new SoapException() с SoapException.ClientFaultCode в качестве типа из этого вызова? очевидно, у вас есть несколько слоев, которые могут дать сбой в коде, который вы показываете выше, и его легко испортить (поверьте мне, я знаю :)). И не вызывайте другие методы, такие как Publisher.publish.., которые будут указывать на то, является ли это объявлением сообщения (т.е. инфраструктурой ASMX) или это ваш код, который возится с исключением..

person gbvb    schedule 23.05.2012
comment
Я попробую это прямо сейчас... Я также попытаюсь просто создать обычное исключение вместо SoapException. - person ganders; 23.05.2012
comment
Редактирование кода кажется правильным, но вы все еще сталкиваетесь с той же проблемой? - person gbvb; 23.05.2012
comment
правильно, все еще видя тот же ответ. Это из-за того, что ДжонСондерс ответил о том, что ASMX не поддерживает ошибки должным образом, или эта ошибка не такая же, как ошибка, которую я вижу? - person ganders; 23.05.2012
comment
хм. Хотя я согласен с тем, что ASMX не справляется с ошибками должным образом, я думаю, что обычно он работает нормально. То, как вы это показываете, похоже, является конфигурацией конечной точки. Вы должны использовать какой-нибудь сетевой сниффер, например fiddler, чтобы увидеть, что отправляется обратно. Тем не менее, я согласен просто использовать либо WCF, либо новые WebAPI, чтобы упростить вашу жизнь, если у вас есть выбор. - person gbvb; 23.05.2012
comment
Хорошо, я запустил Fiddler2 для этого, похоже, что часть, которую мы ищем, имеет это для сообщения об ошибке: существует проблема с ресурсом, который вы ищете, и он не может быть отображен. Я добавлю редактирование № 5 с фактическим ответом, который поймал Fiddler. - person ganders; 23.05.2012
comment
Ознакомьтесь с этой базой знаний: support.microsoft.com/kb/942031 . и попробуйте Резолюцию 7, так как кажется, что это именно то, что вы видите .. :) - person gbvb; 24.05.2012
comment
Извините за мое невежество, я прочитал статью, но все еще немного запутался в том, как реализовать изменение. Должна ли dll, которую необходимо добавить к сопоставлениям обработчиков, быть dll на стороне клиента, которая пытается получить доступ к веб-сервису? Итак, в моем примере моя dll на стороне клиента называется PWD.dll, поэтому я просто добавляю ее в сопоставления обработчиков веб-сайта? Тем временем я попробую ... (если это сработает, пожалуйста, добавьте это как ответ, чтобы я мог отдать вам должное :)) - person ganders; 24.05.2012
comment
Это не клиент. Вам нужно проверить сервер! что-то на сервере могло быть неправильно настроено. Это может быть разрешение 4, но в любом случае проверьте сервер, позволяет ли он фактически обрабатывать веб-службу (asmx) сервером. Кажется, это проблема из того, что я вижу здесь. - person gbvb; 25.05.2012
comment
Итак, эта ссылка говорит, что мне нужно добавить сопоставление обработчиков, чтобы избавиться от сообщения об ошибке, которое я вижу. Но я пытаюсь просто вернуть System.Web.Services.Protocols.SoapException, разве это уже не обрабатывается ASP.NET? - person ganders; 12.06.2012