WebAPI如何在(.NET)客户端反序列化异常

时间:2015-09-30 14:03:14

标签: c# json asp.net-web-api asp.net-web-api2

我有一个webAPI 2控制器,目前它正在抛出一个异常,并在响应消息中将其发送回客户端。 500内部服务器错误,它的自我序列化的例外,我可以在fiddler中看到它的json表示。 (json粘贴在下面)

我一直在尝试找到一种方法将此异常反序列化为.NET Exception对象,但不断收到错误:

  

“找不到会员'ClassName'。”

目前在我的客户端我试图通过以下代码反序列化异常。

if (apiResponse.ResponseCode.Equals(500)) // Unhandled exception on server
{
    var exceptionObject = await response.Content.ReadAsAsync<Exception>();
}

如何在客户端应用程序上正确反序列化此异常对象?理想情况下,我应该能够取回原始的System.InvalidOperationException`对象。

下面是我试图反序列化的响应,如fiddler所示:

  

HTTP / 1.1 500内部服务器错误   缓存控制:无缓存   Pragma:没有缓存   Content-Type:application / json;字符集= utf-8的   到期:-1   服务器:Microsoft-IIS / 10.0   X-AspNet-Version:4.0.30319   X-Powered-By:ASP.NET   日期:2015年9月30日星期三13:43:42 GMT   内容长度:1556

     

{“Message”:“发生了错误。”,“ExceptionMessage”:“UrlHelper.Link必须不返回null。”,“ExceptionType”:“System.InvalidOperationException”,“StackTrace”:“at System.Web .Http.Results.CreatedAtRouteNegotiatedContentResult 1.Execute()\r\n at System.Web.Http.Results.CreatedAtRouteNegotiatedContentResult 1.ExecuteAsync(CancellationToken cancellationToken)\ r \ n在System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext()\ r \ n ---堆栈跟踪结束抛出异常的前一个位置--- \ r \ n在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)\ r \ n在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\ r \ n at System.Web.Http.Controllers.ActionFilterResult.d__2.MoveNext()\ r \ n ---从抛出异常的上一个位置开始的堆栈跟踪结束--- \ r \ n在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (任务任务)\ r \ n在System.Web.Http.Fil的System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\ r \ n中ters.AuthorizationFilterAttribute.d__2.MoveNext()\ r \ n ---从抛出异常的上一个位置开始的堆栈跟踪结束--- \ r \ n在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)\ r \ n \ n在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\ r \ n在System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()“}

2 个答案:

答案 0 :(得分:5)

感谢Serg Rogovtsev的评论,我现在知道你拥有的不是Exception而是HttpError。因此,您必须按原样处理它:

var exceptionObject = await response.Content.ReadAsAsync<System.Web.Http.HttpError>();
但是,我仍然不相信这是一个好主意。 500状态代码通常意味着出现意外错误,并且没有任何东西可以在服务器端捕获它。如果您可以控制服务器,我强烈建议您在那里处理此类错误。 无论如何,客户端无法对此做任何事情,所以它只需要某种错误通知。

旧答案(关于HttpError的评论之前):

序列化的Exception看起来像这样:

{
    "ClassName":"System.Exception",
    "Message":"some exception",
    "Data":null,
    "InnerException":null,
    "HelpURL":null,
    "StackTraceString":null,
    "RemoteStackTraceString":null,
    "RemoteStackIndex":0,
    "ExceptionMethod":null,
    "HResult":-2146233088,
    "Source":null,
    "WatsonBuckets":null
}

您所拥有的只是一个格式化的错误消息,其中包含有关异常的信息。

顺便说一下:我不会尝试在客户端捕获服务器端异常。您需要处理服务器上的错误并向客户端提供足够的信息以通知用户发生了什么。

答案 1 :(得分:0)

我找到了一个获得我想要的json异常的好方法。我在查看ASPNET git存储库中的示例时得到了这个。

在ASPNET Startup.cs配置方法中添加以下内容(仅针对开发环境,因为其他答案中提到500可能对客户端无用)

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    if (env.IsDevelopment())
    {
        app.Use(async (context, next) =>
        {
             try
             {
                  await next();
             }
             catch (Exception ex)
             {
                  if (context.Response.HasStarted)
                  {
                      throw;
                  }
                  context.Response.StatusCode = 500;
                  await context.Response.WriteJsonExcpetionAsync(ex);
              }
        });
    }

    // Other config logic...
}