【问题标题】:How to parse internalexception from WebException Response如何从 WebException 响应中解析内部异常
【发布时间】:2010-11-24 21:25:12
【问题描述】:

我有 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>

我需要从innererror 中取出internalexception 中的消息。最简单的方法是什么?

【问题讨论】:

  • 顺便说一句,ex.Message 已经是一个字符串。你不需要使用.ToString()

标签: c# xml response odata webexception


【解决方案1】:

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

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

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

如果你不知道怎么做,吼,我会搞砸的。

【讨论】:

  • 我尝试使用“docNav = new XPathDocument(responseText);”进行转换但我得到一个“路径中的非法字符”ArgumentException。我首先尝试用 String.Empty 替换单引号,但这没有帮助。如果你能搞砸一些粗糙的东西把这个烂摊子转换成我可以抛出的 .Net 异常,那将非常有帮助。
  • 实际上,在此之前,您使用什么库来访问 odata?你用过odata.codeplex.com的吗?
  • 我只是在使用 VS 2010/.Net 4 中的任何内容。
  • @Mark,新 XPathDocument(responseText) 出错的原因是当 XPathDocument 的 arg 是字符串时,它被视为文档的路径(或 url)......而不是文本的文件。 msdn.microsoft.com/en-us/library/aa336085%28v=VS.71%29.aspx
  • @Mark:换句话说,你应该打电话给XPathDocument(responseStream)
【解决方案2】:

最简单的方法可能是使用如下的正则表达式来提取"&lt;message&gt;"和"&lt;/message&gt;"之间的字符串:

<message>(.+)</message>

这不是非常健壮,也不符合 XML 的精神,但它应该可以工作,除非 XML 变化很大。如果您还没有在您的应用程序中使用 XML 工具,那么您不一定要为了提取此字符串而修改它们。

【讨论】:

  • 问题是我想要的 内的 中有一个 ,而 中有一个 我不想要。
  • @Mark:好点。这就是为什么您不应该使用正则表达式来处理 XML,除非它是一个 非常 简单的情况。 :-) 尝试其他人的答案,除了将初始的“//”更改为“/”以提高效率。
猜你喜欢
  • 2012-06-08
  • 2012-05-14
  • 1970-01-01
  • 1970-01-01
  • 2012-08-19
  • 2019-04-04
  • 1970-01-01
  • 2016-03-30
  • 1970-01-01
相关资源
最近更新 更多