从Web API错误过滤异常堆栈跟踪?

时间:2015-06-03 07:40:27

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

我有一个与之沟通的网络API。

发生异常时,我会得到以下JSON模板:

{
  "Message": "An error has occurred.",
  "ExceptionMessage": "Index was outside the bounds of the array.",
  "ExceptionType": "System.IndexOutOfRangeException",
  "StackTrace": "   at WebApiTest.TestController.Post(Uri uri) in c:\\Temp\\WebApiTest\\WebApiTest\\TestController.cs:line 18\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClassf.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n   at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)"
}

我希望JSON包含的只是“Message”和“ExceptionMessage”属性,但仍然可以控制按需返回完整的堆栈跟踪。

我尝试过使用

GlobalConfiguration.Configuration.IncludeErrorDetailPolicy

但似乎全部或全部,或者只是单个“消息”属性,或者在将其设置为“始终”时获取完整对象。

任何简单的方法来实现这一目标?

将不胜感激。

2 个答案:

答案 0 :(得分:1)

在我的代码中,我使用异常过滤器来执行您要求的操作,请查看以下两个链接以获取更多详细信息

Web API Exception Handling

Web API global error handling

我们在代码中的行为如下:

  1. 创建例外过滤器:

    public class ViewRExceptionFilterAttribute : ExceptionFilterAttribute
    {
    // Global context message for the modifying the context response in case of exception
    private string globalHttpContextMessage;
    
    /// <summary>
    ///     Overriding the OnException method as part of the Filter, which would detect the type of Action and would
    ///     accordingly modify the Http
    ///     context response
    /// </summary>
    /// <param name="context"></param>
    public override void OnException(HttpActionExecutedContext context)
    {
        // Dictionary with Type and Action for various Type actions, current method is called by various types
        Dictionary<Type, Action> dictionaryExceptionTypeAction = new Dictionary<Type, Action>();
    
        // Add an action for a given exception type
        dictionaryExceptionTypeAction.Add(typeof (ViewRClientException), ViewRClientExceptionAction(context.Exception));            
        dictionaryExceptionTypeAction.Add(typeof (Exception), SystemExceptionAction(context.Exception));
    
        // Execute an Action for a given exception type
        if (context.Exception is ViewRClientException)
            dictionaryExceptionTypeAction[typeof (ViewRClientException)]();
       else
            dictionaryExceptionTypeAction[typeof (Exception)]();
    
        // Reset the Context Response using global string which is set in the Exception specific action
        context.Response = new HttpResponseMessage
        {
            Content = new StringContent(globalHttpContextMessage)
        };
    }
    
    /// <summary>
    ///     Action method for the ViewRClientException, creates the Exception Message, which is Json serialized
    /// </summary>
    /// <returns></returns>
    private Action ViewRClientExceptionAction(Exception viewRException)
    {
        return (() =>
        {
            LogException(viewRException);
    
            ViewRClientException currentException = viewRException as ViewRClientException;
    
            ExceptionMessageUI exceptionMessageUI = new ExceptionMessageUI();
    
            exceptionMessageUI.ErrorType = currentException.ErrorTypeDetail;
    
            exceptionMessageUI.ErrorDetailList = new List<ErrorDetail>();
    
            foreach (ClientError clientError in currentException.ClientErrorEntity)
            {
                ErrorDetail errorDetail = new ErrorDetail();
    
                errorDetail.ErrorCode = clientError.ErrorCode;
    
                errorDetail.ErrorMessage = clientError.ErrorMessage;
    
                exceptionMessageUI.ErrorDetailList.Add(errorDetail);
            }
    
            globalHttpContextMessage = JsonConvert.SerializeObject(exceptionMessageUI, Formatting.Indented);
        });
    }
    
  2. 此处ViewRClientException是我的自定义异常类,具有以下架构:

    public class ViewRClientException : Exception
    {
        public ViewRClientException(ErrorType errorType, List<ClientError> errorEntity)
        {
            ErrorTypeDetail = errorType;
            ClientErrorEntity = errorEntity;
        }
    
        public ErrorType ErrorTypeDetail { get; private set; }
        public List<ClientError> ClientErrorEntity { get; private set; }
    }
    

    上面定义的Action方法确保我们获得相关的Json序列化字符串,该字符串可用作Json响应,类似于SystemExceptionAction的作用,用于任何非自定义的泛型异常。实际上我有很多其他自定义异常类别。当前过滤器修改HttpContext.Response

    1. 在WebAPIConfig.cs中注册Exception过滤器,如下所示:

        public static class WebApiConfig
          {
            public static void Register(HttpConfiguration config)
            {
              // Web API configuration and services
      
              // Adding the Generic Exception Filter for the application
              config.Filters.Add(new ViewRExceptionFilterAttribute());
      
              // Web API routes
              config.MapHttpAttributeRoutes();
      
              config.Routes.MapHttpRoute("ControllerActionApi", "api/{controller}/{action}/{userID}",
                  new {userID = RouteParameter.Optional}
                  );
      
              config.Routes.MapHttpRoute("ControllerApi", "api/{controller}/{userID}",
                  new {userID = RouteParameter.Optional}
                  );
            }
         }
      
    2. 现在它应该可以根据需要提供自定义消息

答案 1 :(得分:-2)

不完整的例子。 ClientError&amp; ErrorType ErrorTypeDetail

如果您要参与,请包含所有内容!