WebAPI自定义ExceptionFilterAttribute中的Ninject属性注入不起作用

时间:2014-02-06 21:12:35

标签: error-handling asp.net-web-api ninject

我正在尝试使用Ninject将EventLogger实例注入自定义ExceptionFilterAttribute。每当我运行代码时,EventLogger实例都为null。我已经实现了一个IFilterProvider,以类似的方式为我的自定义AuthorizationFilterAttribute解析依赖关系,并且工作正常。有什么想法吗?

不工作

public class ErrorHandlingAttribute : ExceptionFilterAttribute
{
    [Inject]
    public IEventLogger EventLogger { get; set; }

    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
       EventLogger.LogException(actionExecutedContext.Exception);

        actionExecutedContext.Response = actionExecutedContext.Request.
            CreateResponse(HttpStatusCode.BadRequest, 
            new ServiceErrorResponseDTO("An unhandled exception occurred while calling " + 
                actionExecutedContext.Request.RequestUri.ToString() + 
                ". This event has been logged. If you continue to receive this error contact Weichert"));
    }
}

工作

public class RequireAuthorizationAttribute : AuthorizationFilterAttribute
{
    [Inject]
    public IServiceRepository ServiceRepository { get; set; }

    public override void OnAuthorization(HttpActionContext actionContext)
    {


        #region Header Authentication

        var authHeader = actionContext.Request.Headers.Authorization;
        if (authHeader != null)
        {

自定义IFilterProvider

public class NinjectWebApiFilterProvider : IFilterProvider
{
    private IKernel _kernel;

    public NinjectWebApiFilterProvider(IKernel kernel)
    {
        _kernel = kernel;
    }

    public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
    {
        var controllerFilters = actionDescriptor.ControllerDescriptor.GetFilters().Select(instance => new FilterInfo(instance, FilterScope.Controller));
        var actionFilters = actionDescriptor.GetFilters().Select(instance => new FilterInfo(instance, FilterScope.Action));

        var filters = controllerFilters.Concat(actionFilters);

        foreach(var filter in filters)
        {
            _kernel.Inject(filter.Instance);
        }

        return filters;
    }
}

NinjectWebCommon CreateKernel Method

private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        // Ad Ninject support for Web API.
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);

        GlobalConfiguration.Configuration.Services.Add(typeof(IFilterProvider), 
            new NinjectWebApiFilterProvider(kernel));

        RegisterServices(kernel);
        return kernel;
    }

NinjectWebCommon绑定

private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<ServiceDbContext>().To<ServiceDbContext>();
        kernel.Bind<IServiceRepository>().To<ServiceRepository>();

        kernel.Bind<CareerDevelopmentDbContext>().To<CareerDevelopmentDbContext>();
        kernel.Bind<ICareerDevelopmentRepository>().To<CareerDevelopmentRepository>();
        kernel.Bind<ICareerDevelopmentService>().To<CareerDevelopmentService>();

        kernel.Bind<IEventLogger>().To<ServiceEventLogger>();
        kernel.Bind<IFilterProvider>().To<NinjectWebApiFilterProvider>().WithConstructorArgument("kernel", kernel);
    }        

2 个答案:

答案 0 :(得分:4)

我遇到了同样的问题,并且通过将其添加到WebApiConfig.cs中的过滤器集合中以相同的方式配置我的错误处理程序,这意味着它没有被我添加的FilterProvider实现处理。所以我这样做了:

public class LoggingExceptionFilterAttribute : ExceptionFilterAttribute, IExceptionFilter
{
    // this is what I wanted injected
    private IEmailService emailService;

    public LoggingExceptionFilterAttribute(IEmailService service)
    {
        emailService = service;
    }

    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        // my implementation here
    }
}

然后我在NinjectWebCommon中注册了这样:

kernel.Bind<System.Web.Http.Filters.IExceptionFilter>().To<LoggingExceptionFilterAttribute>().InSingletonScope();

然后在WebApiConfig我意识到我可以抓住DependencyResolver所以我这样做了:

config.Filters.Add((IFilter)config.DependencyResolver.GetService(typeof(IExceptionFilter)));

现在Ninject处理构建我的异常过滤器,我甚至可以进行构造函数注入而不需要[Inject]属性,而且我不必将ExceptionFilterAttribute添加到每个API控制器。

答案 1 :(得分:1)

好的,您还必须确保绑定自定义IFilterProvider。编写 Ninject.Web.WebApi 时,Nuget包是不稳定的,如果您使用它,它会自动为您执行。以同样的方式 Ninject.MVC3 为您的常规控制器执行此操作。

只要确保你有这个绑定,被替换的DependencyResolver也将通过你的Ninject内核寻找IFilterProvider实现:

kernel.Bind<IFilterProvider>().To<NinjectWebApiFilterProvider>();

然后,您的NinjectWebApiFilterProvider将按照您的代码启动并将依赖项注入您的过滤器。