Как проанализировать internalexception из ответа WebException - PullRequest
2 голосов
/ 25 ноября 2010

У меня есть код C #, который выполняет POST для веб-службы OData, что приводит к вставке записи в базу данных. Если есть исключение, например, нарушение первичного ключа, я хочу записать и записать сообщение об ошибке. Тем не менее, сообщение содержится в XML. Вот мой обработчик исключений:

catch (WebException ex)
{
  if (ex.Status == WebExceptionStatus.ProtocolError)
  {
      string responseText = string.Empty;

      using (Stream responseStream = ((HttpWebResponse)ex.Response).GetResponseStream())
      {
          using (StreamReader streamReader = new StreamReader(responseStream))
          {
              responseText = streamReader.ReadToEnd();
          }
      }
      Debug.WriteLine(responseText);
      return responseText;
  }
  else
  {
      Debug.WriteLine(ex.Message.ToString());
      return ex.Message.ToString();
  }
}

Вот что я получаю в ответе:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
  <code></code>
  <message xml:lang="en-US">An error occurred while processing this request.</message>
  <innererror>
    <message>An error occurred while updating the entries. See the inner exception for details.</message>
    <type>System.Data.UpdateException</type>
    <stacktrace>   at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)&#xD;
   at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)&#xD;
   at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)&#xD;
   at System.Data.Services.Providers.ObjectContextServiceProvider.SaveChanges()&#xD;
   at System.Data.Services.DataService    1.HandleNonBatchRequest(RequestDescription description)&#xD;
   at System.Data.Services.DataService    1.HandleRequest()</stacktrace>
    <internalexception>
      <message>Violation of PRIMARY KEY constraint 'PK_Customer_CustomerId'. Cannot insert duplicate key in object 'VertexBilling.Customer'.&#xD;
The statement has been terminated.</message>
      <type>System.Data.SqlClient.SqlException</type>
      <stacktrace>   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)&#xD;
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)&#xD;
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()&#xD;
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)&#xD;
   at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()&#xD;
   at System.Data.SqlClient.SqlDataReader.get_MetaData()&#xD;
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)&#xD;
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)&#xD;
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)&#xD;
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)&#xD;
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)&#xD;
   at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)&#xD;
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)&#xD;
   at System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary    2 identifierValues, List    1 generatedValues)&#xD;
   at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)</stacktrace>
    </internalexception>
  </innererror>
</error>

Мне нужно вывести сообщение из внутреннего исключения из внутренней ошибки. Какой самый простой способ сделать это?

Ответы [ 2 ]

1 голос
/ 25 ноября 2010

Вам следует использовать инструментарий XML, он уже есть в вашем распоряжении в .net, и он устраняет проблемы неоднозначности при обработке xml как текста (это кошмар, ожидающий, в приведенном выше xml у вас есть два узла сообщения)

  1. Загрузка строки в XmlDocument
  2. использование // error / innerError / internalexception / message xpath для извлечения необходимого узла

в качестве альтернативы вы можете создать небольшой фрагмент кодакоторый извлекает / десериализует innerException в экземпляр Exception и может повторно использовать его для других вызовов.

Если вы не знаете, как это сделать, реветь, я что-то взбучу.

0 голосов
/ 25 ноября 2010

Самый простой способ , вероятно, заключается в использовании регулярного выражения, подобного следующему, для извлечения строки между "<message>" и "</message>":

<message>(.+)</message>

Это не очень надежно и не в духе XML, но должно работать, если XML сильно не меняется. И если вы еще не используете инструменты XML в своем приложении, вам не обязательно изменять их только для извлечения этой строки.

...