2017-10-18 240 views
-1

我们目前的许多控制器是这样的:处理异常

[HttpPost] 
public List<Foo> Post([FromBody]Bar model) 
{ 
    if (model == null) 
    { 
     throw new ArgumentNullException(); 
    } 

    try 
    { 
     // business logic 
    } 
    catch (Exception ex) 
    { 
     // logging 
    } 

    return dto; 
} 

大量的代码正在这里虽然重复。我想要做的是实现一个基本的控制器来处理异常,所以我可以返回标准化反应ErrorPayload领域,Success,等

此前.NET的核心,这是可以通过提供覆盖OnException但是,这似乎不适用于.net核心API控制器。当我的控制器主体发生错误时,如何合并此异常逻辑以返回自定义响应?

我想此,作为起点:

[HttpPost] 
public StandardFoo Post([FromBody]Bar model) 
{ 
    if (model == null) 
    { 
     throw new ArgumentNullException(); 
    } 

    // business logic 

    return new StandardFoo(){Payload: dto}; 
} 

凡异常,由模型验证或business logic冒泡一些的逻辑块与包含异常细节的属性返回一个新StandardFoo抛出。

+0

documentation:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/error-handling – Nkosi

+1

您正在关注错误的方法。你应该避免使用基于控制器的异常处理方法,以及控制器中的try catch。应尽可能保持管理者的精益,并将责任合并到另一个班级中。这似乎是[XY问题](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。 – Nkosi

+0

@Nkosi你能否提供一个简单而简洁的例子,说明如何在抛出异常时使用上述控制器并返回自定义响应? – user666

回答

1

我会建议创建一个自定义操作过滤器。这可以在WebApiConfig寄存器方法中的每个传入请求中进行打包(请参见下文)。

在我的示例中,我检查模型状态是否有效。

如果不是,我创建一个ErrorResponse并发回一个错误的请求。

您不必像下面的例子那样简单地发回模型状态,就可以返回任何你想要的东西。

通过这种方式,在所有端点上都具有需要验证的模型以及此时在管道中执行的任何其他检查的统一。

注意:因为我们正在全局注册此属性,所以我们不必在其他任何地方声明它,从这一点开始,所有传入流量都将由此类进行检查。

public class ValidateModelAttribute : ActionFilterAttribute 
     { 
      public override void OnActionExecuting(HttpActionContext actionContext) 
      { 

       if (!actionContext.ModelState.IsValid) 
       { 
        actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState); 
       } 
      } 

      public override bool AllowMultiple 
      { 
       get { return false; } 
      } 
     } 



public static class WebApiConfig 
    { 
     public static void Register(HttpConfiguration config) 
     { 
      // Web API configuration and services 
      config.Filters.Add(new ValidateModelAttribute()); 
     } 
    } 
2

如果不久,您就不应该捕获并处理控制器中的异常。


相反,您需要在代码中分开正常流和错误流,然后分别处理错误流。指示正常流程不可行的主要方法之一是提出.NET异常(并使用它)。但是:

  • 控制器操作应该只知道正常流量。没有try-catch逻辑等等。
  • 用于输入验证使用ActionFilter。您可以为所有控制器设置全局过滤器或定义特定的每个操作。请参阅文档中的Filters section。 ASP.NET Core也允许执行Model Validation

  • 在控制器操作执行期间,应尽快引发异常并停止进一步的管道执行。是的,可以在任何级别(动作级别,服务/业务层级,DA层级等)上引发异常。

如何处理引发的异常呢?