查看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;
}