WebApi自定义过滤器与构造函数中的注入接口不会被调用

时间:2018-02-06 11:55:18

标签: c# asp.net-web-api dependency-injection ninject

我的问题陈述与this question相同,即在属性/过滤器中使用注入的服务。我已经尝试过B Z给出的解决方案,以下是我给出的解决方案的代码。

//marker attribute
public class AuthorizeViewAttribute : Attribute { }

//filter
public class AuthorizeViewFilter : IAuthorizationFilter
{
    private readonly IAccessRightsService _iAccessRightService;
    public AuthorizeViewFilter(IAccessRightsService iAccessRightService)
    {
        _iAccessRightService = iAccessRightService;
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        RoleFeature roleFeature = _iAccessRightService.GetRoleFeatures();

        if (roleFeature.IsView)
        {
            //redirect to controller
        }
    }      
}

以下是我使用的ninject绑定:

this.BindFilter<AuthorizeViewFilter>(System.Web.Mvc.FilterScope.Controller, 0)
        .WhenControllerHas<AuthorizeViewAttribute>();

我在属性中不需要任何参数,所以我认为我不需要像this answer中提到的那样使用WithConstructorArgument

但我的过滤器永远不会被调用。我在AuthorizeViewAttribute中放置了一个默认构造函数,调试后发现控件跳转到AuthorizeViewAttribute中的默认构造函数并继续使用控制器方法。

我找不到任何解决方法。有什么建议吗?

1 个答案:

答案 0 :(得分:2)

简短的故事:您似乎试图在webapi控制器上使用MVC过滤器和MVC绑定。这就是为什么它不起作用。

长篇小说:首先创建一个webapi过滤器提供程序(注意,您需要Ninject.Extensions.Factories个包来让Ninject解析Func<AuthorizeViewFilter>

public class AuthorizeViewFilterProvider : System.Web.Http.Filters.IFilterProvider
{
    private readonly Func<AuthorizeViewFilter> _authorizeViewFilterFactory;

    public AuthorizeViewFilterProvider(Func<AuthorizeViewFilter> authorizeViewFilterFactory)
    {
        this._authorizeViewFilterFactory = authorizeViewFilterFactory;
    }

    public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
    {
        if(!actionDescriptor.GetCustomAttributes<AuthorizeViewAttribute>().Any())
            return Enumerable.Empty<FilterInfo>();

        return new[]
        {
            new FilterInfo(this._authorizeViewFilterFactory(), FilterScope.Action)
        };
    }
}

然后创建一个webapi过滤器

public class AuthorizeViewFilter : System.Web.Http.Filters.IAuthorizationFilter
{
    private readonly IAccessRightsService _iAccessRightService;
    public AuthorizeViewFilter(IAccessRightsService iAccessRightService)
    {
        _iAccessRightService = iAccessRightService;
    }

    public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(
        HttpActionContext actionContext,
        CancellationToken cancellationToken,
        Func<Task<HttpResponseMessage>> continuation)
    {
        RoleFeature roleFeature = _iAccessRightService.GetRoleFeatures();

        if (roleFeature.IsView)
        {
            return continuation();
        }
        else
          return Task.FromResult(actionContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Access denied"));
    }
}

然后,在绑定设置中绑定FilterProvider:

this.Bind<System.Web.Http.Filters.IFilterProvider>().To<AuthorizeViewFilterProvider>();