2

AutofacでMVC4を使用してWebアプリを開発しています。ロガー サービスを挿入するグローバル例外フィルターがあるため、次のように App_Start で初期化しています。

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(DependencyResolver.Current.GetService<IExceptionFilter>());
    }

これは、フィルターの一般的なレイアウトです。 public class ErrorHandlerAttribute : HandleErrorAttribute { private readonly ILoggerService logger;

    public ErrorHandlerAttribute(ILoggerService logger)
    {
        this.logger = logger;
    }

    public override void OnException(ExceptionContext filterContext)
    {
        //dostuff
    }

    public void LogError(ExceptionContext context)
    {
        try
        {
            logger.Error(context.Exception.Message, context.Exception);
        }
        catch (Exception) { }
    }
}

Autofac を使用していなかったら、次のようになっていました。

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new ErrorHandlerAttribute());

        filters.Add(new ErrorHandlerAttribute
        {
            View = "UnauthorizedException",
            ExceptionType = typeof(UnauthorizedAccessException)
        });

        filters.Add(new ErrorHandlerAttribute
        {
            View = "PageNotFound",
            ExceptionType = typeof(NotImplementedException)
        });
    }

ErrorHandlerAttribute は、MVC の HandleErrorAttribute から派生した、私のカスタム例外フィルターです。

Autofacのインジェクションと単一のフィルターを使用しながら、カスタムエラーページにリダイレクトする機能を維持できるようにしたいと思います(例外を処理できるように構築したため)。残念ながら、Web や他のフォーラムで可能な解決策を探しても、これを行う方法を見つけることができないようです。多くの構成変更、さまざまな登録、コレクションの解決などを試しました。

私がそれを機能させたい方法は、次のようになります。

    builder.RegisterType<ErrorHandlerAttribute>().As<IExceptionFilter>().InstancePerHttpRequest();
    builder.RegisterType<ErrorHandlerAttribute>().As<IExceptionFilter>()
        .WithProperties(new List<NamedParameter>() { new NamedParameter("ExceptionType", typeof(UnauthorizedAccessException)), new NamedParameter("View", "UnauthorizedAccess") })
        .InstancePerHttpRequest();
    builder.RegisterType<ErrorHandlerAttribute>().As<IExceptionFilter>()
        .WithProperties(new List<NamedParameter>() { new NamedParameter("ExceptionType", typeof(NotImplementedException)), new NamedParameter("View", "UnderConstruction") })
        .InstancePerHttpRequest();
    builder.RegisterFilterProvider();

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        DependencyResolver.Current.GetServices<IExceptionFilter>().ForEach(f => filters.Add(f));
    }

驚くべきことに、これはコンパイルおよび実行されますが、3 つの IExceptionFilter インスタンスはすべて正常で、デフォルトの ErrorHandlerAttribute (View="Error" および ExceptionType=typeof(object) を使用) です。

Autofac がサービスの最後の登録をデフォルトとして取得するという事実を認識しており、PreserveExistingDefaults を使用するだけでなく、3 つの登録のうち 2 つをコメントしようとしましたが、すべての例外フィルターにはデフォルト値が付いています。

WithProperties 拡張メソッドを誤解していますか、それとも私が望むものを実装する別の同様の方法はありますか?

編集1

Alex の提案に感謝します。NamedPropertyParameter を使用してステートメントの順序を切り替えることで解決しました。

builder.RegisterType<ErrorHandlerAttribute>().As<IExceptionFilter>()
    .WithProperties(new List<NamedPropertyParameter> { new NamedPropertyParameter("ExceptionType", typeof(UnauthorizedAccessException)), new NamedPropertyParameter("View", "UnauthorizedAccess") })
    .InstancePerHttpRequest();
builder.RegisterType<ErrorHandlerAttribute>().As<IExceptionFilter>()
    .WithProperties(new List<NamedPropertyParameter> { new NamedPropertyParameter("ExceptionType", typeof(NotImplementedException)), new NamedPropertyParameter("View", "UnderConstruction") })
    .InstancePerHttpRequest();
builder.RegisterType<ErrorHandlerAttribute>().As<IExceptionFilter>().InstancePerHttpRequest();
4

1 に答える 1