13

Mvc\WebApi アプリケーションにグローバルな ExceptionFilter が次のように登録されています。

public virtual void RegisterHttpFilters(HttpConfiguration config)
{
    config.Filters.Add(new MyExceptionFilter(_exceptionHandler));
}

MyExceptionFilter は次のとおりです。

public class MyExceptionFilter : ExceptionFilterAttribute
{
    private readonly IMyExceptionHandler m_exceptionHandler;

    public MyExceptionFilter(IMyExceptionHandler exceptionHandler)
    {
        m_exceptionHandler = exceptionHandler;
    }

    public override void OnException(HttpActionExecutedContext context)
    {
        Exception ex = context.Exception;
        if (ex != null)
        {
            object response = null;
            HttpStatusCode statusCode = m_exceptionHandler != null
                ? m_exceptionHandler.HandleException(ex, out response)
                : HttpStatusCode.InternalServerError;
            context.Response = context.Request.CreateResponse(statusCode, response ?? ex);
        }

        base.OnException(context);
    }
}

このフィルターは、すべての例外を json オブジェクトとして返し、一部の IMyExceptionHandler 実装が返されるオブジェクトをカスタマイズできるようにします。

これはすべてうまくいきます。一部のメッセージ ハンドラーで例外が発生するまで:

public class FooMessageHandler : DelegatingHandler
{
    private readonly Func<IBar> _barFactory;
    public FooMessageHandler(Func<IBar> barFactory)
    {
        _barFactory = varFactory;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.Properties["MY_BAR"] = _barFactory();
        return base.SendAsync(request, cancellationToken);
    }
}

ご覧のとおり、このハンドラーはいくつかのコンポーネントを作成し、それを現在の http 要求メッセージに入れます。FuncOfIBar で例外が発生すると、イエロー スクリーン オブ デスが表示されます。私の ExceptionFilter は呼び出されません。

メッセージハンドラーで例外を明確にキャッチしてHttpResponseExceptionを返そうとしましたが、何も変更されません-まだYSODを取得しています:

public class XApplicationInitializerMessageHandler : DelegatingHandler
{
    private readonly Func<IXCoreApplication> _appFactory;
    private readonly IXExceptionHandler m_exceptionHandler;

    public XApplicationInitializerMessageHandler(Func<IXCoreApplication> appFactory, IXExceptionHandler exceptionHandler)
    {
        ArgumentValidator.EnsureArgumentNotNull(appFactory, "appFactory");
        _appFactory = appFactory;
        m_exceptionHandler = exceptionHandler;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        try
        {
            request.SetApplication(_appFactory());
        }
        catch (Exception ex)
        {
            object resultObject = null;
            HttpStatusCode statusCode = m_exceptionHandler != null
                ? m_exceptionHandler.HandleException(ex, out resultObject)
                : HttpStatusCode.InternalServerError;
            HttpResponseMessage responseMessage = request.CreateResponse(statusCode, resultObject ?? ex);

            throw new HttpResponseException(responseMessage);
        }
        return base.SendAsync(request, cancellationToken);
    }
}

}

例外が発生する場所に関係なく、アプリの動作を同じにしたい: ApiController またはメッセージ ハンドラー。

これを行う方法?

Application_Error については知っていますが、HttpApplication のカスタマイズを変更できないようにしたいと考えています。

4

5 に答える 5

8

スローする代わりに、 :HttpResponseExceptionを返すだけです。HttpResponseMessage

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    try
    {
        request.SetApplication(_appFactory());
    }
    catch (Exception ex)
    {
        object resultObject = null;
        HttpStatusCode statusCode = m_exceptionHandler != null
            ? m_exceptionHandler.HandleException(ex, out resultObject)
            : HttpStatusCode.InternalServerError;
        HttpResponseMessage responseMessage = request.CreateResponse(statusCode, resultObject ?? ex);

        return Task<HttpResponseMessage>.Factory.StartNew(() => responseMessage);
    }
    return base.SendAsync(request, cancellationToken);
}
于 2012-08-08T14:09:19.997 に答える
5

グローバル例外フィルターが実行されていないという同じ問題がありました。解決策は、WebAPI例外フィルターをASP.NETMVC例外フィルターとは異なるグローバルコレクションで構成する必要があることでした。

したがって、ASP.NET MVCエラー処理を構成するには、次のコマンドを実行します。

System.Web.Mvc.GlobalFilters.Filters.Add(new MyMvcExceptionFilter());

ただし、Web APIエラー処理では、次を実行する必要があります。

System.Web.Http.GlobalConfiguration.Configuration.Filters.Add(new MyWebApiExceptionFilter());

Web APIに関する私の限られた経験から、このタイプの状況は典型的です。表面的には、使用されるパターンはASP.NET MVCに非常に似ており、すぐに馴染みがあります。これにより、1つのコードを記述すると両方のフレームワークに影響があるという錯覚が生じますが、実際には、その下にある実装は大部分または完全に分離されており、すべてを作成するには非常に類似した2つのバージョンのコードを記述する必要があります。仕事。

Web API例外処理に関する優れたリファレンス:http ://www.asp.net/web-api/overview/web-api-routing-and-actions/exception-handling

于 2013-03-04T18:18:20.410 に答える
5

私が成功のために行ったことは、属性ベースのアプローチを使用することです。例外処理を使用するアクションのそれぞれにカスタム属性を配置します。

[ExceptionHandling] 
public IEnumerable<string> Get()

カスタム例外処理属性は次のように実装されます。

public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {}

ご覧のとおり、カスタム属性は ExceptionFilterAttribute から継承されています。次に、OnException メソッドをオーバーライドするだけです。次にできることは、例外のタイプを調べて、ビジネス ルールまたはニーズに合ったものに従って処理することです。場合によっては、サーバー上の例外を飲み込むだけかもしれません。クライアントに通知する場合は、HttpResponseException をスローして、メッセージ、コール スタック、内部例外などのすべての関連情報を保持できます。

さらにインスピレーションを得るには、この素晴らしいブログ投稿をご覧ください: ASP.NET Web API Exception Handling

于 2012-08-10T11:39:02.780 に答える
2

startup.cs:

config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());

GlobalExceptionHandler を使用すると、委任ハンドラーで例外をキャッチし、カスタム JSON オブジェクトを返すことができることがわかりました。

于 2015-11-02T01:25:54.503 に答える