【问题标题】:ServiceStack catch (WebServiceException ex) - has wrong ErrorCodeServiceStack catch (WebServiceException ex) - 有错误的 ErrorCode
【发布时间】:2013-02-20 14:38:53
【问题描述】:

在我的 ServiceStack 服务中,我抛出了一个具有内部异常的异常。当我在客户端捕获到 WebServiceRequest 时,ErrorCode 是内部异常类型名称。

这对我很不利,因为它不允许我响应服务器上抛出的特定异常类型。

我不明白为什么 ServiceStack 是这样设计的。捕获较低级别的异常并用信息更丰富、有时对最终用户友好的异常进行包装是非常典型的。

如何更改默认行为,使其使用表面级别的异常而不是最内层的异常?

【问题讨论】:

    标签: exception-handling servicestack


    【解决方案1】:

    查看https://github.com/ServiceStack/ServiceStack/wiki/Error-Handling 的第一个示例后,我决定查看DtoUtils.HandleException,如下所示:

        public static object HandleException(IResolver iocResolver, object request, Exception ex)
        {
            if (ex.InnerException != null && !(ex is IHttpError))
                ex = ex.InnerException;
    
            var responseStatus = ex.ToResponseStatus();
    
            if (EndpointHost.DebugMode)
            {
                // View stack trace in tests and on the client
                responseStatus.StackTrace = GetRequestErrorBody(request) + ex;
            }
    
            Log.Error("ServiceBase<TRequest>::Service Exception", ex);
    
            if (iocResolver != null)
                LogErrorInRedisIfExists(iocResolver.TryResolve<IRedisClientsManager>(), request.GetType().Name, responseStatus);
    
            var errorResponse = CreateErrorResponse(request, ex, responseStatus);
    
            return errorResponse;
        }
    

    第一条指令将异常替换为其内部异常。我不确定那是什么想法。这对我来说似乎违反直觉,所以我只是在我的 AppHost 类中重新实现了该方法,删除了第一个 if 语句块:

        public override void Configure(Container container)
        {
            ServiceExceptionHandler += (request, exception) => HandleException(this, request, exception);
        }
    
        /// <remarks>
        /// Verbatim implementation of DtoUtils.HandleException, without the innerexception replacement.
        /// </remarks>
        public static object HandleException(IResolver iocResolver, object request, Exception ex)
        {
            var responseStatus = ex.ToResponseStatus();
    
            if (EndpointHost.DebugMode)
            {
                // View stack trace in tests and on the client
                responseStatus.StackTrace = DtoUtils.GetRequestErrorBody(request) + ex;
            }
    
            var log = LogManager.GetLogger(typeof(DtoUtils));
            log.Error("ServiceBase<TRequest>::Service Exception", ex);
    
            if (iocResolver != null)
                DtoUtils.LogErrorInRedisIfExists(iocResolver.TryResolve<IRedisClientsManager>(), request.GetType().Name, responseStatus);
    
            var errorResponse = DtoUtils.CreateErrorResponse(request, ex, responseStatus);
    
            return errorResponse;
        }
    

    这显然不理想,因为我不得不复制一堆与我在原始实现中遇到的问题完全无关的代码。这让我觉得每当我更新 ServiceStack 时我都必须维护这个方法。我很想在这里找到一种更好的方法来实现这一点。

    无论如何,我的客户端代码中都有我喜欢的异常处理:

    catch (WebServiceException ex)
    {
        if (ex.ErrorCode == typeof (SomeKindOfException).Name)
        {
            // do something useful here
        }
        else throw;
    }
    

    【讨论】:

      【解决方案2】:

      您似乎不必维护一堆代码。您正在编写一种方法来实现您自己的错误处理。您可以尝试在自己的方法中调用 DtoUtils.HandleException(this, request, exception) 并修改返回的 HttpError 对象。不确定您是否有权更改您正在寻找的所有属性/值。

      public static object HandleException(IResolver iocResolver, object request, Exception ex)
      {
          HttpError err = (HttpError)DtoUtils.HandleException(this, request, ex);
          err.Reponse = ex.InnerException; 
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-12
        • 1970-01-01
        • 2012-03-25
        • 1970-01-01
        • 2011-12-28
        • 2021-12-09
        • 2021-11-03
        • 1970-01-01
        相关资源
        最近更新 更多