4

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

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

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

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

4

2 回答 2

3

在查看了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;
}
于 2013-02-20T16:11:35.263 回答
1

您似乎不必维护一堆代码。您正在编写一种方法来实现您自己的错误处理。您可以尝试在自己的方法中调用 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; 
}
于 2013-02-20T18:11:08.937 回答