Ninject Property Injection in WebAPI custom ExceptionFilterAttribute Not Working

南笙酒味 提交于 2020-01-04 14:31:13

问题


I am trying to use Ninject to inject an EventLogger instance into a custom ExceptionFilterAttribute. Whenever I run the code, the EventLogger instance is null. I have implemented an IFilterProvider to resolve dependencies in a similar manner for my custom AuthorizationFilterAttribute, and that works fine. Any ideas?

Not Working

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"));
    }
}

Working

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)
        {

Custom 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 Bindings

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);
    }        

回答1:


Ok, you have to make sure you are binding your custom IFilterProvider as well. As of writing the Ninject.Web.WebApi Nuget package is unstable and would do that automatically for you, if you were using it. Just in the same fashion Ninject.MVC3 does this for your regular controllers.

Just make sure you have this binding, and the replaced DependencyResolver will look for IFilterProvider implementation via your Ninject kernel as well:

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

Then your NinjectWebApiFilterProvider will kick in and inject dependencies into your filters as per your code.




回答2:


I had the same problem and was configuring my error handler the same way by adding it to the filter collection in WebApiConfig.cs which meant it wasn't getting handled by the FilterProvider implementation I had added. So I did this instead:

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
    }
}

Then I registered this in NinjectWebCommon like so:

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

And then in WebApiConfig I realized that I could get a hold of the DependencyResolver so I did this:

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

Now Ninject handles constructing my exception filter and I can even do constructor injection instead of needing [Inject] attributes and I don't have to add my ExceptionFilterAttribute to every API controller.



来源:https://stackoverflow.com/questions/21614139/ninject-property-injection-in-webapi-custom-exceptionfilterattribute-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!