处理Service Fabric中的聚合异常

时间:2017-05-18 14:59:43

标签: c# exception-handling asp.net-core azure-service-fabric

我们说我有一个Web API服务,它调用我的用户服务来返回用户个人资料信息等。

UserProfileService可以抛出UserNotFoundException。抛出时,它被序列化并作为AggregateException中的内部异常发送,可以在调用方法中捕获。此服务使用Service Fabric的服务远程处理进行RPCing。

我的WebAPI正在调用我的服务:

[HttpGet]
public async Task<IActionResult> Get(int id)
{
    try
    {
        var profile = await _userService.GetProfileAsync(int id);
        return Json(profile);
    } catch (AggregateException ae)
    {
        // Here I want to call NotFound() if `UserNotFoundException`
        //   was thrown, otherwise...
        return StatusCode(StatusCodes.Status500InternalServerError);
    }
}

这里有几个问题:

  1. 我该怎样处理预期的例外情况?
  2. 天真地我做这样的事情:

    try { /* ... */ } catch (AggregateException ae)
    {
        foreach(var e in ae.InnerExceptions)
        {
            if (e is UserNotFoundException)
            {
                return NotFound();
            }
        }
    
        return errorResponse ?? StatusCode(StatusCodes.Status500InternalServerError);
    }
    

    但问题是,如果有多个例外,只有一个会赢得#34;。并且,我相信 - 尽管无法保证,最早添加的Exception将具有优先权,因为它们在InnerExceptions中的索引较低。我在想这个,这个解决方案会没问题吗?我抛出自定义异常的唯一一次是当我知道它们应该抛出时,当然?

    这引出了我的另一个问题:

    1. 在什么情况下,您会在AggregateException
    2. 中检索多个例外情况

      当你Task a召唤Task b来调用Task cc投注,b不投掷,{{1} }抛出,你得到包含aa例外的汇总异常?

2 个答案:

答案 0 :(得分:2)

我会向后回答你的问题:

2)AggregateException有一个contructor,允许IEnumerable<Exception>作为参数。这是它如何包含多个内部异常。这意味着您的聚合异常不会包含多个内部异常,除非您明确抛出具有多个内部异常的AggregateException。假设您有Task a来电Task b来电Task c。如果c引发了一个未在ab中捕获的异常,a会抛出AggregateException内部AggregateException c引发的内部异常。

1)你的例子很好用。如果你想要它缩短一点,你可以通过内部异常来捕捉它:

try
{
    // ...
}
catch (AggregateException ex) when (ex.InnerException is UserNotFoundException)
{
    // ...
}
catch (AggregateException ex) when (ex.InnerException is SomeOtherException)
{
    // ...
}

您也可以使用一些if语句来捕获它们,就像您在示例中所做的那样:

try
{
    // ...
}
catch (AggregateException ex)
{
    if (ex.InnerException is UserNotFoundException)
    {
        // ...
    }
    else if (ex.InnerException is SomeOtherExeption)
    {
        // ...
    }
}

答案 1 :(得分:1)

我建议在所有相关类中抛出异常,并且只捕获Web服务中的异常,向Web服务调用者报告一条错误消息。保持异常处理尽可能简单。

改写:如果在任何代码中出现问题,只需throw new Exception(),其中一个字符串表示发生了什么以及在哪里。您try/catch所在的唯一地点位于[httpget] Get()

如果你真的知道你在做什么,你可以实现序列化的异常,但是你不会在这里问这个: - )