如何从 WebException 响应中解析内部异常

发布于 2024-10-04 10:52:20 字数 4140 浏览 3 评论 0原文

我有 C# 代码,可以对 OData Web 服务执行 POST,从而将记录插入到数据库中。如果出现异常,例如主键违规,我想捕获并记录错误消息。但是,该消息包含在 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();
  }
}

这是我在responseText 中得到的内容:

<?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>

我需要从内部错误的内部异常中获取消息。最简单的方法是什么?

I have C# code that does a POST to an OData web service, which results in a record being inserted into a database. If there is an exception, such as a primary key violation, I want to capture and log the error message. However, the message is contained within XML. Here is my exception handler:

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();
  }
}

Here is what I get in responseText:

<?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)
   at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)
   at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
   at System.Data.Services.Providers.ObjectContextServiceProvider.SaveChanges()
   at System.Data.Services.DataService    1.HandleNonBatchRequest(RequestDescription description)
   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'.
The statement has been terminated.</message>
      <type>System.Data.SqlClient.SqlException</type>
      <stacktrace>   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary    2 identifierValues, List    1 generatedValues)
   at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)</stacktrace>
    </internalexception>
  </innererror>
</error>

I need to get the message out of the internalexception out of the innererror. What's the easiest way to do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧人 2024-10-11 10:52:20

您应该使用 XML 工具包,您已经在 .net 中使用了它,并且它消除了将 xml 视为文本时的歧义问题(这是一场噩梦,在上面的 xml 中您有两个消息节点)

  1. 将字符串加载到 XmlDocument
  2. 使用 / /error/innerError/internalException/message xpath 来提取所需的节点

,或者您可以构建一小段代码,将 innerException 提取/反序列化为 Exception 实例,并可以将其重用于其他调用。

如果你不知道怎么做,吼叫,我会搞砸一些东西。

You should use XML toolkit, you already have it at your disposal in .net and it removes ambiguity problems when treating xml as text (its a nightmare waiting to happen, in the above xml you have two message nodes)

  1. Load string to XmlDocument
  2. use //error/innerError/internalexception/message xpath to extract the needed node

alternatively you can build a small piece of code which would extract/deserialize the innerException into an Exception instance and can reuse it for other calls.

If you don't know how to do this, howler, I'll bang something up.

再可℃爱ぅ一点好了 2024-10-11 10:52:20

最简单方法可能是使用如下正则表达式来提取 """"< 之间的字符串/code>:

<message>(.+)</message>

这不是非常健壮,也不符合 XML 的精神,但它应该可以工作,除非 XML 变化很大。如果您尚未在应用程序中使用 XML 工具,则不一定要为了提取该字符串而加速它们。

The easiest way is probably to use a regular expression like the following to extract the string between "<message>" and "</message>":

<message>(.+)</message>

That's not extremely robust, and it's not in the spirit of XML, but it should work unless the XML varies much. And if you're not already using XML tools in your app, you don't necessarily want to rev them up just to extract this string.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文