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

大量のコードを維持する必要はないようです。独自のエラー処理を実装する 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 に答える